สำหรับตัวอย่างที่เฉพาะเจาะจงของ " สามารถรีเซ็ตรหัสผ่าน " ฉันขอแนะนำให้ใช้การแต่งเพลงมากกว่าการสืบทอด (ในกรณีนี้การสืบทอดของอินเทอร์เฟซ / สัญญา) เพราะโดยทำสิ่งนี้:
class Foo : IResetsPassword {
    //...
}
คุณระบุทันที (ในเวลารวบรวม) ที่ชั้นเรียนของคุณ ' สามารถรีเซ็ตรหัสผ่าน ' แต่ถ้าในสถานการณ์ของคุณการปรากฏตัวของความสามารถนั้นมีเงื่อนไขและขึ้นอยู่กับสิ่งอื่น ๆ คุณจะไม่สามารถระบุสิ่งต่าง ๆ ในเวลารวบรวมได้อีกต่อไป จากนั้นฉันแนะนำให้ทำสิ่งนี้:
class Foo {
    PasswordResetter passwordResetter;
}
ตอนนี้ที่รันไทม์คุณสามารถตรวจสอบmyFoo.passwordResetter != nullก่อนดำเนินการนี้ หากคุณต้องการแยกชิ้นส่วนให้มากขึ้น (และคุณวางแผนที่จะเพิ่มความสามารถอื่น ๆ อีกมากมาย) คุณสามารถ:
class Foo {
    //... foo stuff
}
class PasswordResetOperation {
    bool Execute(Foo foo) { ... }
}
class SendMailOperation {
    bool Execute(Foo foo) { ... }
}
//...and you follow this pattern for each new capability...
UPDATE 
หลังจากที่ฉันอ่านคำตอบและความคิดเห็นอื่น ๆ จาก OP ฉันเข้าใจว่าคำถามไม่ได้เกี่ยวกับการแต่งเพลงประกอบ ดังนั้นฉันคิดว่าคำถามเกี่ยวกับวิธีการระบุความสามารถของวัตถุโดยทั่วไปดีขึ้นในสถานการณ์ดังนี้
class BaseAccount {
    //...
}
class GuestAccount : BaseAccount {
    //...
}
class UserAccount : BaseAccount, IMyPasswordReset, IEditPosts {
    //...
}
class AdminAccount : BaseAccount, IPasswordReset, IEditPosts, ISendMail {
    //...
}
//Capabilities
interface IMyPasswordReset {
    bool ResetPassword();
}
interface IPasswordReset {
    bool ResetPassword(UserAccount userAcc);
}
interface IEditPosts {
    bool EditPost(long postId, ...);
}
interface ISendMail {
    bool SendMail(string from, string to, ...);
}
ตอนนี้ฉันจะพยายามวิเคราะห์ตัวเลือกทั้งหมดที่กล่าวถึง:
ตัวอย่างที่สอง OP:
if (account.CanResetPassword)
       ((IResetsPassword)account).ResetPassword();
else
       Print("Not allowed to reset password with this account type!");
สมมติว่ารหัสนี้กำลังรับคลาสบัญชีพื้นฐานบางอย่าง (เช่น: BaseAccountในตัวอย่างของฉัน); สิ่งนี้ไม่ดีเนื่องจากมันเป็นการแทรกบูลีนในคลาสฐานทำให้เกิดมลพิษกับรหัสที่ทำให้ไม่มีเหตุผลที่จะอยู่ที่นั่น
OP ตัวอย่างแรก:
if (account is IResetsPassword)
       ((IResetsPassword)account).ResetPassword();
else
       Print("Not allowed to reset password with this account type!");
เพื่อตอบคำถามนี้มีความเหมาะสมมากกว่าตัวเลือกก่อนหน้านี้ แต่ขึ้นอยู่กับการใช้งานมันจะทำลายหลักการ L ของของแข็งและอาจตรวจสอบเช่นนี้จะแพร่กระจายผ่านรหัสและทำให้การบำรุงรักษาเพิ่มเติมยากขึ้น 
แอนเซอร์ของ CandiedOrange:
account.ResetPassword(authority);
หากResetPasswordวิธีนี้ถูกแทรกในBaseAccountชั้นเรียนแล้วมันยังก่อมลพิษชั้นฐานด้วยรหัสที่ไม่เหมาะสมเช่นในตัวอย่างที่สองของ OP
คำตอบของ Snowman:
AccountManager.resetPassword(otherAccount, adminAccount.getAccessToken());
นี่เป็นวิธีแก้ปัญหาที่ดี แต่ก็ถือว่าความสามารถนั้นเป็นแบบไดนามิก (และอาจเปลี่ยนแปลงตลอดเวลา) อย่างไรก็ตามหลังจากที่ฉันอ่านความคิดเห็นต่าง ๆ จาก OP ฉันเดาว่าการพูดคุยที่นี่เกี่ยวข้องกับ polymorphism และคลาสที่กำหนดไว้แบบสแตติก EG: ในAccountManagerตัวอย่างนี้การตรวจสอบการอนุญาตจะเป็นการสืบค้นไปยัง DB; ในคำถาม OP การตรวจสอบคือความพยายามในการหล่อวัตถุ
ข้อเสนอแนะอื่นจากฉัน:
ใช้รูปแบบวิธีการเทมเพลตสำหรับการแยกสาขาระดับสูง ลำดับชั้นของคลาสที่กล่าวถึงจะถูกเก็บไว้เหมือนเดิม เราสร้างตัวจัดการที่เหมาะสมมากขึ้นสำหรับวัตถุเพื่อหลีกเลี่ยงการปลดเปลื้องและคุณสมบัติ / วิธีการที่ไม่เหมาะสมในการสร้างคลาสพื้นฐาน
//Template method
class BaseAccountOperation {
    BaseAccount account;
    void Execute() {
        //... some processing
        TryResetPassword();
        //... some processing
        TrySendMail();
        //... some processing
    }
    void TryResetPassword() {
        Print("Not allowed to reset password with this account type!");
    }
    void TrySendMail() {
        Print("Not allowed to reset password with this account type!");
    }
}
class UserAccountOperation : BaseAccountOperation {
    UserAccount userAccount;
    void TryResetPassword() {
        account.ResetPassword(...);
    }
}
class AdminAccountOperation : BaseAccountOperation {
    AdminAccount adminAccount;
    override void TryResetPassword() {
        account.ResetPassword(...);
    }
    void TrySendMail() {
        account.SendMail(...);
    }
}
คุณสามารถผูกการดำเนินการกับคลาสบัญชีที่เหมาะสมโดยใช้พจนานุกรม / hashtable หรือทำการดำเนินการแบบรันไทม์โดยใช้วิธีการขยายใช้dynamicคำสำคัญหรือเป็นตัวเลือกสุดท้ายใช้เพี้ยนเพียงครั้งเดียวเพื่อส่งวัตถุบัญชีไปยังการดำเนินการ (ใน กรณีนี้จำนวนการปลดเปลื้องจะมีเพียงครั้งเดียวเท่านั้นในตอนเริ่มต้นของการปฏิบัติการ)