59

我不确定什么看起来更好,或者我什么时候真正在抽象类和属性中使用,或者什么时候使用非抽象属性。我会尝试做一个简单的例子。假设我有这个:

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等等应该是抽象的。

现在,如果可以,我什么时候应该或应该使用抽象属性?

4

5 回答 5

96

当您没有默认实现并且派生类必须实现它时,请使用抽象属性。

当您在基类中有实现但希望允许覆盖时,请使用虚拟属性。

使用override关键字覆盖成员。将成员标记为sealed override不应再次被覆盖。

不要将该属性标记为abstract或者virtual如果您不希望它被覆盖。

使用new关键字来隐藏一个非抽象的、非虚拟的成员(这很少是一个好主意)。

如何:定义抽象属性

我发现抽象属性经常出现在设计中,这意味着它们将具有特定于类型的逻辑和/或副作用。您基本上是在说,“这是所有子类都必须具有的数据点,但我不知道如何实现它”。但是,可能不希望包含大量逻辑和/或导致副作用的属性。这是一个重要的考虑因素,尽管没有固定的正确/错误方式来做到这一点。

看:

就个人而言,我发现我经常使用抽象方法,但很少使用抽象属性。

于 2012-09-03T21:58:07.837 回答
43

我知道我想让他们做什么,我不在乎他们是怎么做的:界面。

我知道我想让他们做什么,我不在乎他们如何做一些事情,但我对他们(或至少他们中的大多数人)将如何做其他事情有坚定的想法:抽象类。

我知道我想让他们做什么,以及他们中的大多数人会怎么做:带有虚拟成员的具体类。

你可以有其他情况,例如没有抽象成员的抽象类(你不能有一个实例,但它提供什么功能,它提供了完全),但它们很少见,通常是因为特定的层次结构干净而公然地为给定的问题提供自己。

(顺便说一句,我不会将 Peter 视为人类的一种,而是将每个彼得视为碰巧被称为 Peter 的人类的一个实例。以这种方式选择示例代码并不公平,但是当你重新考虑这类问题,它比平时更相关)。

于 2012-09-03T22:10:24.680 回答
17

抽象成员只是您必须覆盖的虚拟成员。您将它用于必须实现但不能在基类中实现的东西。

如果您想创建一个虚拟属性,并且希望它必须在继承您的类的类中被覆盖,那么您可以将其设为抽象属性。

例如,如果你有一个动物类,它的呼吸能力无法仅从它是动物的信息中确定,但这是非常关键的:

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; } }

}
于 2012-09-03T22:00:02.890 回答
7

当所有子类必须实现方法/属性时使用抽象。如果不需要每个子类都实现它,那么就不要使用它。

至于您的示例,如果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抽象是正确的,因为每辆汽车都有制造商,并且需要能够告诉用户该制造商是谁。

于 2012-09-03T21:58:10.363 回答
2

抽象属性将用于您希望类始终公开该属性,但您无法确定该属性的实现 - 将其留给/强制继承类这样做。

这里有一个示例,其中抽象类被命名Shape,并且它公开了一个抽象Area属性。您不能Area在基类中实现该属性,因为每种形状的面积公式都会改变。所有形状都有一个区域(某种),所以所有形状都应该暴露属性。

您的实现本身看起来还不错。试图为 a 想一个合理的抽象属性示例Human,但想不出任何合理的东西。

于 2012-09-03T21:58:31.367 回答