【问题标题】:Override property of the base class with a derived class用派生类覆盖基类的属性
【发布时间】:2017-07-05 06:17:00
【问题描述】:

在 C# 代码中,如果 Rebar 类派生自 Reinforcement 类并且 RebarShape 类继承 ReinforcementShape 类。是否可以用RebarShape类覆盖基类中的属性ReinforcementShape

   public class ReinforcementShape
   {
   }

   public class RebarShape : ReinforcementShape
   {
   }

   public class Reinforcement
   {
        public ReinforcementShape Shape { get; set; }
   }


   public class Rebar : Reinforement
   {
        // I want to override the Shape property
        // but with its derived class which is RebarShape

        // override the base property somehow!
        public RebarShape Shape { get; set; }
   }

更新:

当前的实现有什么问题?

在基地:

public virtual ReinforcementShape Shape { get; set; }

派生:

public new RebarShape Shape { get; set; }

【问题讨论】:

  • 你不能覆盖一个属性并改变它的返回类型。

标签: c# inheritance properties polymorphism


【解决方案1】:

你可以用泛型做到这一点,不需要重写基类成员:

public class Reinforcement<T> where T: ReinforcementShape 
{
    public <T> Shape { get; set; }
}

public class Rebar : Reinforement<RebarShape>
{
}

现在您可以轻松创建ReBar 的实例并访问它的Shape-property,它是RebarShape 的实例:

var r = new Rebar();
r.Shape = new RebarShape();

尝试将ReinforcementShape 的实例分配给该属性将导致编译时错误,此时只有RebarShape 有效。

编辑:根据您的编辑。您只能通过覆盖它的实现来覆盖一个成员,而不是它的返回值。因此,在您的情况下,使用 virtual 不会做任何事情。但是,正如 R.Rusev 已经提到的,您只需要派生成员上的 new-keyword,它实际上将提供一个全新的成员,该成员与您的基类中的成员具有相同的名称。但实际上它是一个完全不同的成员,与前者没有任何共同之处。但是,当您编写以下内容时

Reinforcement r = new Rebar();
// assign value to Shape
var shape = r.Shape;

使用的是原始实现,而不是您的新实现。所以shape 将是ReinforcementShape 类型而不是RebarShape。解决这个问题的唯一方法是首先将r 声明为Rebar

Rebar r = new Rebar();
// assign value to Shape
var shape = r.Shape;

但这会让您的应用程序的任何用户感到困惑,也许对您自己也是如此。我一般不建议使用该关键字。最好使用第一种方法。

【讨论】:

  • 不幸的是我不能使用泛型。因为我需要对这些类的几个属性执行此操作。
  • @Vahid:那么您应该将其他属性添加到您的问题中。一般来说,泛型是更好的方法(与new关键字答案相比)
【解决方案2】:

您可以使用new 关键字来执行此操作。因此,您对 Rebar 类的定义将如下所示。

public class Rebar : Reinforement
{
    public new RebarShape Shape
    {
        get { return (RebarShape)base.Shape; }
        set { base.Shape = value; }
    }
}

【讨论】:

  • new-关键字不会覆盖,而是隐藏基类的实现。无论如何,当您使用派生类的实例作为基类的变量时,即使使用关键字,也会使用原始成员,而不是新成员。
  • 谢谢。你能告诉我基类中的实现吗?我也希望能够在基类中设置。
  • @Vahid 基类保持不变。
  • @HimBromBeere 你是对的。我只是觉得这就是瓦希德想要做的。所以他不必每次使用 Rebar 时都施放 RebarShape。
猜你喜欢
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 1970-01-01
  • 2018-07-31
  • 1970-01-01
  • 2013-05-16
  • 2010-11-04
  • 1970-01-01
相关资源
最近更新 更多