2012-09-03 163 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是的,在编写示例代码时,我们都会想到不好的名字,通常这并不重要,但这是一个比大多数问题更重要的问题。 –

相关问题