2012-09-03 204 views
29

我真的不確定什麼看起來更好,什麼時候我真的在抽象類和屬性中使用,何時使用非抽象屬性。我會盡量舉個簡單的例子。假設我有這個:不知道什麼時候使用抽象屬性,什麼時候不使用

abstract class Human 
{ 
    public GenderType Gender { get; set; } 
    public string Name { get; set; } 
    public Date Born { get; set; } 
    public bool IsNerd { get; set; } 

    abstract public void Speak(); 
    abstract public void Sleep(); 
    abstract public void AnoyingPeopleOnStackOverflow(); 
    //... so on 
} 

class Peter : Human 
{ 
    //Peter is special, he got a second name 
    //But thats all, everything else is the same as like on other humans 
    public string SecondName { get; set; } 

    //...override abstract stuff 
} 

這樣好嗎?據我瞭解,如果我不想重寫它,我不必使用抽象屬性。而在這種情況下就可以了,只要像SpeakSleep等這樣的方法應該是抽象的。

現在,如果這是好的,什麼時候會或應該使用抽象屬性?

+1

「什麼時候會或應該使用抽象屬性」---當您想要聲明子類必須提供特定的方法實現時 – zerkms

+1

1)如果這是Java,則可能沒有任何問題。你可能只是使用「界面」。這基本上是你在C#中做的,不是嗎?2)我個人的感覺是,如果它需要成爲「契約」的一部分,那麼在你的抽象類中聲明它是恰當的。換句話說,我認爲你所做的完全沒問題。恕我直言...... – paulsm4

+1

@ paulsm4你也可以用C#來做到這一點。 –

回答

56

如果沒有默認實現並且派生類必須實現它,請使用抽象屬性。

當您在基類中有一個實現但想要允許覆蓋時使用虛擬屬性。

使用override關鍵字來覆蓋成員。如果不應該再次覆蓋成員,則將該成員標記爲sealed override

如果您不希望它被覆蓋,請不要標記爲abstractvirtual

使用new關鍵字來隱藏非抽象的非虛擬成員(這很少是個好主意)。

How to: Define Abstract Properties

我發現抽象屬性經常發生在這意味着它們將具有特定類型的邏輯和/或副作用的設計。你基本上是說,「這是一個所有子類必須具備的數據點,但我不知道如何實現它」。 然而,,包含大量邏輯和/或導致副作用的屬性可能不合意。這是一個重要的考慮因素,雖然沒有固定的方法來做到這一點。

請參見:

就個人而言,我發現我使用抽象方法,但經常抽象屬性很少。

4

當所有子類都有來實現方法/屬性時使用抽象。如果不需要每個子類都實現它,那就不要使用它。

至於你的例子,如果每個人不需要SecondName,那麼就不需要在基類中創建一個抽象屬性。另一方面,如果每個人都需要第二個名字,那麼將其作爲一個抽象的屬性。抽象屬性的正確用法的

例子:

public class Car 
{ 
    public abstract string Manufacturer { get; } 
} 

public class Odyssey : Car 
{ 
    public override string Manufacturer 
    { 
     get 
     { 
      return "Honda"; 
     } 
    } 
} 

public class Camry : Car 
{ 
    public override string Manufacturer 
    { 
     get 
     { 
      return "Toyota"; 
     } 
    } 
} 

製作Maker抽象是正確的,因爲每汽車有一個製造商,需要能夠分辨出誰是製造者是用戶。

1

抽象屬性將用於你希望類總是公開屬性的地方,但是你不能固定那個屬性的實現 - 讓它繼續/迫使繼承類去做。

有一個示例here,其中抽象類名爲Shape,並且它公開了一個抽象Area屬性。您不能在基類中實現Area屬性,因爲區域的公式會針對每種類型的形狀發生更改。所有形狀都有一個區域(某種形式),所以所有的形狀都應該暴露該屬性。

你的實現本身看起來很好。正試圖想出一個Human的抽象屬性的明智例子,但想不出任何合理的。

11

抽象成員只是您必須覆蓋的虛擬成員。你用它來實現某些東西,但不能在基類中實現。

如果您想製作一個虛擬屬性,並且希望它在繼承您的類的類中被覆蓋,那麼您將使它成爲一個抽象屬性。

比如你有一個動物類,它的呼吸能力將不可能從它的動物的信息只是detemine,但它的東西,這是非常重要的:

public abstract class Animal { 

    public abstract bool CanBreathe { get; } 

} 

對於魚和狗的實現是不同的:

public class Dog : Animal { 

    public override bool CanBreathe { get { return !IsUnderWater; } } 

} 

public class Fish : Animal { 

    public override bool CanBreathe { get { return IsUnderWater; } } 

} 
26

我知道我希望他們做,我不在乎他們是如何做到這一點:接口。我知道我希望他們做什麼,我不在乎他們是怎麼做的,但是我對他們如何(或者至少他們大部分)會做其他事情有着堅定的想法:抽象類。

我知道我想讓他們做什麼,以及他們中的大多數人會這樣做:具有虛擬成員的具體類。

你可以有其他情況,例如,一個沒有抽象成員的抽象類(你不能擁有一個抽象類的實例,但它提供的是什麼功能,它提供的是完全的),但它們更爲罕見,通常是由於特定的層次結構自然而然地向給定的問題。 (順便說一下,我不會把彼得看作是一種人類,而是把每個彼得當作一個恰好被稱爲彼得的人的一個實例,用這種方式選擇示例代碼是不公平的,但是當你想到這種問題時,它比平時更貼切)。

+3

+1 - 同意,'Peter'應該是'Human'的一個子類的一個實例,例如。 'HumansWithTwoNames' –

+2

@TimMedora是的,在編寫示例代碼時,我們都會想到不好的名字,通常這並不重要,但這是一個比大多數問題更重要的問題。 –

相關問題