【问题标题】:Not sure when to use an abstract property and when not不确定何时使用抽象属性,何时不使用
【发布时间】:2012-09-03 21:54:20
【问题描述】:

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

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) 如果这是 Java,可能不会有任何问题。您可能只使用“界面”。这本质上就是您在 C# 中所做的,不是吗? 2)我个人的感觉是,如果它需要成为“合同”的一部分,那么在你的抽象类中声明它是合适的。换句话说,我认为你所做的一切都很好。恕我直言...
  • @paulsm4 你也可以用 C# 做到这一点。

标签: c# .net oop properties abstract


【解决方案1】:

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

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

使用override 关键字覆盖成员。如果不应再次覆盖该成员,请将其标记为 sealed override

如果您不想被覆盖,请不要将该属性标记为 abstractvirtual

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

How to: Define Abstract Properties

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

见:

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

【讨论】:

    【解决方案2】:

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

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

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

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

    (顺便说一句,我不会将 Peter 视为人类的一种,而是将每个 peter 视为恰好被称为 Peter 的人类的一个实例。以这种方式选择示例代码并不公平,但是当您考虑此类问题时,它比平时更贴切)。

    【讨论】:

    • +1 - 同意,Peter 应该是Human 子类的实例,例如HumansWithTwoNames
    • @TimMedora 是的,我们在编写示例代码时都会想到坏名字,通常这并不重要,但这是一个比大多数问题更重要的问题。
    【解决方案3】:

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

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

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

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

    【讨论】:

      【解决方案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 抽象是正确的,因为每辆汽车都有制造商,并且需要能够告诉用户该制造商是谁。

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

          猜你喜欢
          • 2011-02-03
          • 2015-08-26
          • 1970-01-01
          • 2014-07-12
          • 1970-01-01
          • 1970-01-01
          • 2010-11-25
          • 2018-05-22
          相关资源
          最近更新 更多