2011-05-18 100 views
3

請考慮下面的設計:密封抽象類的屬性

public interface IBook 
{ 
    string Author { get; set; } 

    string Title { get; set; } 
} 

abstract class BaseBook : IBook 
{ 
    private string _title; 

    public virtual string Author 
    { 
     get 
     { 
      Console.WriteLine("Base book GET!"); 
      return _title; 
     } 
     set 
     { 
      Console.WriteLine("Base book SET!"); 
      _title = value; 
     } 
    } 

    public string Title { get; set; } 
} 

class Book : BaseBook 
{ 
} 

class SuperBook : Book 
{ 
    public override string Author 
    { 
     get 
     { 
      Console.WriteLine("SuperBook GET!"); 
      return base.Author; 
     } 
     set 
     { 
      Console.WriteLine("SuperBook SET!"); 
      base.Author = value; 
     } 
    } 

    public string Title { get; set; } 
} 

有什麼辦法使密封防止財產在派生類中被重寫的BaseBook基類Title財產(如BookSuperBook類)?

+0

你爲什麼要這樣的事情?有什麼特別的原因讓用戶不應該被允許覆蓋你的財產? – 2011-05-18 13:11:33

回答

2

如果您編譯程序時,您會收到以下警告:

prog.cs(63,19):警告CS0108: SuperBook.Title' hides inherited member BaseBook.Title」。如果隱藏的目的

這意味着你的SuperBook.Title躲藏起來從BaseBook標題中使用新的 關鍵字。隱藏與重寫不同,因爲該成員不是虛擬的。隱藏會發生什麼:如果編譯器將您的對象視爲SuperBook類的實例,它將調用SuperBook.Title方法。但是,如果編譯器將您的實例視爲BaseBook類,則將調用BaseBook.Title

例如:

SuperBook b1 = new SuperBook(); 
Console.Writeline(b1.Title); // will result in a call to SuperBook.Title 
BaseBook b2 = b1; 
Console.Writeline(b1.Title); // will result in a call to BaseBook.Title 

如果您的虛擬財產,那麼結果是最派生實現總是會被調用,因爲編譯器使用一個虛擬表,找到調用哪個方法。

最後,如果您希望該屬性是虛擬的,以便每個呼叫都可以解析爲SuperBook.Title,但不希望用戶在更多派生類上覆蓋它,則必須標記屬性sealed override

3

如果它不是虛擬的,那麼它不能被覆蓋,它只能被隱藏(使用關鍵字new)。 與Java不同,C#方法(和通過擴展屬性)不是隱式虛擬的,而是明確的。

1

無論如何,您將無法覆蓋Title屬性,除非它標記爲virtual。有些人使用new操作員隱藏了你無法阻止的內容。

+0

是的,你是對的:''''''你無法阻止它被使用新操作符的人隱藏。 – 2011-05-19 09:52:50

1

您已經無法重寫BaseBook.Title。 SuperBook.Title實際上隱藏了BaseBook.Title而不是覆蓋它。它應該真的有新的關鍵字,如果隱藏是有意的;事實上,你會得到一個編譯器警告的效果。

-3

在Title屬性上使用「密封」關鍵字。

+0

這不起作用,因爲標題不是虛擬的,因此不能密封。 – Gal 2011-05-18 14:11:39