埃裏克利珀特只是blogged on this very topic。
它的基本要點是確保一個類可以「信任」受保護方法的調用者。在這方面,共享一個公共基類的類(即使該公共基類定義了受保護的方法)本質上是陌生的。
埃裏克的例子是基於銀行申請的想法。而不是重建他的榜樣,我就吐出在這裏:
// Good.dll:
public abstract class BankAccount
{
abstract protected void DoTransfer(
BankAccount destinationAccount,
User authorizedUser,
decimal amount);
}
public abstract class SecureBankAccount : BankAccount
{
protected readonly int accountNumber;
public SecureBankAccount(int accountNumber)
{
this.accountNumber = accountNumber;
}
public void Transfer(
BankAccount destinationAccount,
User authorizedUser,
decimal amount)
{
if (!Authorized(user, accountNumber)) throw something;
this.DoTransfer(destinationAccount, user, amount);
}
}
public sealed class SwissBankAccount : SecureBankAccount
{
public SwissBankAccount(int accountNumber) : base(accountNumber) {}
override protected void DoTransfer(
BankAccount destinationAccount,
User authorizedUser,
decimal amount)
{
// Code to transfer money from a Swiss bank account here.
// This code can assume that authorizedUser is authorized.
// We are guaranteed this because SwissBankAccount is sealed, and
// all callers must go through public version of Transfer from base
// class SecureBankAccount.
}
}
// Evil.exe:
class HostileBankAccount : BankAccount
{
override protected void Transfer(
BankAccount destinationAccount,
User authorizedUser,
decimal amount) { }
public static void Main()
{
User drEvil = new User("Dr. Evil");
BankAccount yours = new SwissBankAccount(1234567);
BankAccount mine = new SwissBankAccount(66666666);
yours.DoTransfer(mine, drEvil, 1000000.00m); // compilation error
// You don't have the right to access the protected member of
// SwissBankAccount just because you are in a
// type derived from BankAccount.
}
}
當你提出什麼似乎像一個沒有腦子,如果允許再發生那種有心計的,你在這裏看到的將是可能的。現在你知道受保護的方法調用要麼來自你的類型(你可以控制),要麼來自你直接繼承的類(你在編譯時知道)。如果它向任何從聲明類型繼承的人打開,那麼你永遠不會知道可以調用受保護方法的類型。
當您將您的BaseClass
變量初始化爲您自己的類的實例時,編譯器只會看到變量類型爲BaseClass
,這使您處於信任圈之外。編譯器不會分析所有的分配調用(或潛在的分配調用)以確定它是否「安全」。
Thanks Adam :)這真的很有幫助。 – DotNetGuy 2010-01-21 17:19:16
@DotNetGuy:謝謝;如果這回答您的問題,請記住將其標記爲您接受的答案,以便其他人可以更輕鬆地找到答案。 – 2010-01-21 17:36:37