2011-05-19 62 views
16

爲什麼在實現接口時允許更改屬性中getter或setter的可見性和存在性?將替代者添加到替代屬性

interface IFoo 
{ 
    string Bar { get; } 
} 

class RealFoo : IFoo 
{ 
    public RealFoo(string bar) 
    { 
     this.Bar = bar; 
    } 

    public string Bar { get; private set; } 
} 

class StubFoo : IFoo 
{ 
    public string Bar { get; set; } 
} 

...並且在執行抽象類時做法不合法嗎?

abstract class AbstractFoo : IFoo 
{ 
    public abstract string Bar { get; } 
} 

class RealFoo : AbstractFoo 
{ 
    public RealFoo(string bar) 
    { 
     this.Bar = bar; 
    } 

    // Cannot override because 'Bar' does not have an overridable set accessor 
    public override string Bar { get; private set; } 
} 
+2

在您的示例中,您將*代碼添加到接口實現中,因爲沒有setter,但您正在改變抽象類實現中的可見性。所以它不一樣。 – jv42 2011-05-19 12:11:55

+1

@ jv42因爲setter是* private *,所以在實現中沒有改變可視性。限制是任意的和愚蠢的...... C#也可以被指定爲允許覆蓋僅適用於當它們不是私有時獲取或設置。或者它可以允許'公共字符串Bar {override get;私人設置; }' – 2014-10-25 00:35:00

+0

@JimBalter我同意可能有機制來改變訪問者的可見性。您可能想要檢查C#6中會發生什麼,我已經看到了一些有趣的新屬性。 – jv42 2014-10-26 09:42:00

回答

12

該接口聲明該類必須具有的公共屬性(它只是一個契約)。這意味着你需要擁有這些屬性,但可以添加到它們。

抽象類聲明這些屬性的實際結構。所以如果你在抽象基礎中沒有setter,你就不能在實現中添加它。
當您編寫override override修飾符時,它會在基類中查找要覆蓋的內容。

0

抽象類是一個無法實例化的類,但必須從中繼承。抽象類可以完全實現,但通常部分實現或根本不實現,從而封裝了繼承類的通用功能。

相反,接口是一個完全抽象的成員集合,可以被認爲是定義行爲契約。接口的實現完全由開發人員完成。

從MSDN http://msdn.microsoft.com/en-us/library/scsyfw1d(v=VS.71).aspx

+1

好吧,這意味着在類層次結構中添加抽象基類將強制您在某些派生類中添加空/異常拋出的setter實現。不是最優雅的行爲。 – ndeuma 2011-05-19 12:27:22

+2

這個「答案」並沒有涉及實際提出的問題。 – 2014-10-25 00:39:39

0

兩者按照C#規範

是,用於實現 的接口可以不具有 存取改性劑的存取器。如果只有一個 訪問被用於實現 接口,其他訪問可以用訪問修飾符來聲明 :

public interface I 
{ 
    string Prop { get; } 
} 
public class C: I 
{ 
    public Prop { 
    get { return "April"; }  // Must not have a modifier here 
     internal set {...} // Ok, because I.Prop has no set accessor 
    } 
} 

這意味着它是確定已修改了一個類實現的訪問接口。然而,抽象類聲明瞭一個實現,你不能用派生類來改變它。

+1

'abstract'屬性沒有實現。 「抽象類聲明實現」是什麼意思?抽象類是否任意限制了實現,而接口不會隨意限制實現? – binki 2014-01-29 17:48:56

+0

是的,抽象類可以有實現。抽象類可能缺乏實現或可能不完全實現。抽象類只能用於派生其他類。 – 2014-01-30 11:56:56

+1

「抽象類可以有實現」 - @ binki表示抽象*屬性*沒有實現。你的迴應沒有解決他的評論。沒有什麼理由讓C#不允許像'public string Bar {override get;私人設置; }' – 2014-10-25 00:38:49

7

如果你將吸氣劑和吸氣劑想象成它們最終成爲的方法,它可能會變得更加清晰。

在接口的情況下,你要定義這樣的:「實現這個接口必須包括該方法的所有班」

interface IFoo 
{ 
    string GetBar(); 
} 

這可以理解爲 的你都做類:

class RealFoo : IFoo 
{ 
    public string GetBar(); 
    private void SetBar(string value); 
} 

它們也實現了SetBar(),但是這並不重要;他們履行了界面定義的合同並且是有效的。

抽象類,而另一方面是這樣的:

abstract class AbstractFoo : IFoo 
{ 
    public abstract string GetBar(); 
} 

這意味着所有子類必須GetBar()

您所做的類提供了一個方法體是這樣的:

class RealFoo : AbstractFoo 
{ 
    public override string GetBar(); 
    public override void SetBar(string value); 
} 

通過將override修飾符放在SetBar方法的前面,編譯器期望在基類中找到抽象或虛擬版本。你沒有,所以編譯失敗。

+0

這意味着屬性實際上只是setters和getters的捷徑,並且對於良好的oo-design原則沒有任何規定。 – 2013-03-16 23:03:05

+2

所以你間接地說C#將不得不添加像'public string Bar {override get;組; }'然後我們在實現抽象屬性的時候就不會受到任意限制。這實際上是有道理的。 – binki 2014-01-29 17:53:46

+1

@binki它確實有道理,這就是爲什麼這些答案沒有,限制是任意的,而且設計很差。 C#不需要「添加語法」,它可以簡單地採用OP提供的語法並對其進行智能處理,而不是要求我們明確提供後備變量。 – 2014-10-25 00:29:38