【问题标题】:Understanding polymorphism in general (c# example)一般理解多态性(c# 示例)
【发布时间】:2014-07-22 19:33:34
【问题描述】:

我目前正在自学 C# 的一些基本概念,并且正在尝试抽象类和多态性。我以为我掌握了基本概念,但事实证明这个概念并不像我理解的那样起作用:)。但是 - 我希望我能得到一些可以清除灰尘的答案:)。

我要完成的整个任务是扩展一个抽象基类并将扩展与基类的对象一起使用。喜欢这里:

我有一个抽象类,它实现了一个抽象属性,例如:

public abstract class BaseClass
{
   public abstract MyProperty mP{get;}
}

房产在哪里

public abstract class MyProperty 
{
   public abstract string PropertyName{get;}
}

现在我正在为一个实际的实现派生 MyProperty 类,例如

public class DerivedProperty : MyProperty
{
  public override string PropertyName
  {
    get
    {
      return this._name;
    }
  }

  private _name = "Property1";

 /* some other implementation follows here...... */
}

根据我对多态性和继承的理解,现在应该可以从 BaseClass 实例化派生类并使用 DerivedProperty 的对象覆盖属性 MyProperty,如下所示:

public class DerivedClass : BaseClass
{
  public override DerivedProperty mP
  {
    get
    {
      return dP;
    }
  }

  private DerivedProperty dP = new DerivedProperty();

  /* more implementation follows here...... */
}

因为 DerivedProperty 同时是 MyProperty 和 DerivedProperty 的对象,所以可以在引用 MyProperty 或 DerivedProperty 的地方使用它。至少这是我的想法,但似乎这是错误的。 现在我想知道 - 为什么多态性在无法实现上述情况时如此有用?因为即使我尝试这样的事情:

public class DerivedClass : BaseClass
{
  public override MyProperty mP
  {
    get
    {
      return dP as DerivedProperty;
    }
  }

  private DerivedProperty dP = new DerivedProperty();

  /* more implementation follows here...... */
}

我仍然只得到我的基础对象 MyProperty 而不是我想要得到的扩展对象 DerivedProperty。 我知道为什么我会得到这些结果——我只是觉得我不合逻辑:)。是真的像多态性应该工作还是我的实现只是废话,我必须以不同的方式来获得我的扩展属性?

在这里感谢您的帮助!

【问题讨论】:

  • 只是为了让您知道。 m__ 通常是为私有字段保留的前缀(例如 m_darkCage_darkCage)。公共属性通常使用大写首字母命名(例如BrightRoom)。 Property 后缀是为依赖属性保留的。在现实生活中的示例中,您通常不会在类名中使用Class 字符串(在此示例中可能还不错)。 /* */ cmets 通常用于注释代码块。文本 cmets 通常由// 创建。你会发现大部分项目(大部分时间)都遵守这些规则。
  • 这些规则有例外(例如,设计者创建的控件名称有时没有前缀m__,但开发人员仍然接受这些)。学习 c# 命名约定很好,因为它们被广泛使用。

标签: c# polymorphism overriding abstract-class


【解决方案1】:

您必须为被覆盖的属性提供相同的类型。您可以稍后在抽象 BaseClass 中使用它。覆盖时,成员的参数和返回值必须相同。这通常不是问题。

我准备了以下示例,我的代码看起来与您的相似。

在某些情况下,我看到添加了具有更具体类型和不同(更具体)名称的第二个属性:

public abstract class BaseCar
{
    public abstract BaseDriver Driver { get; }
}

public abstract class BaseDriver
{
    public abstract string Name { get; set; }
}

public class AgressiveDriver : BaseDriver
{
    public override string Name { get; set; }
}

public class FastCar : BaseCar
{
    private AgressiveDriver _agressiveDriver = new AgressiveDriver();

    public override BaseDriver Driver { get { return _agressiveDriver; } }
    public AgressiveDriver AgressiveDriver { get { return _agressiveDriver; } }
}

第二种方法是使用泛型:

public abstract class BaseCar<TDriver> 
    where TDriver : BaseDriver
{
    public abstract TDriver Driver { get; }
}

public abstract class BaseDriver
{
    public abstract string Name { get; set; }
}

public class AgressiveDriver : BaseDriver
{
    public override string Name { get; set; }
}

public class FastCar : BaseCar<AgressiveDriver>
{
    private AgressiveDriver _agressiveDriver = new AgressiveDriver();

    public override AgressiveDriver Driver { get { return _agressiveDriver; } }
}

但我认为第一种方法更好,因为创建/使用 BaseCar 对象没有问题(例如,要创建 BaseCar 变量,您必须指定类型参数)。为更具体的属性创建更具体的名称也是有意义的。

【讨论】:

  • 谢谢 - 这帮助我了解我做错了什么或将来我必须做得更好
【解决方案2】:

我认为您不需要额外的复杂性。您在抽象类中有一个抽象类。如果您只是在学习/重新学习,那么您已经跳过了几个简单的步骤来理解。下面是一个更简单的示例。

public abstract class Shape
{

   public abstract double GetArea();
   public abstract double Circumference();
}


public class Square: Shape
{
    public double width {get; set;}

    public override double GetArea()
    {
        return width * width;
    }

    public override Circumference()
    {
        return width * 4;
    }
}

您现在可以实例化一个 Square 或创建一个 Circle 类,并能够在您使用 Shape 的任何地方使用。

【讨论】:

    猜你喜欢
    • 2015-07-14
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 2011-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多