【问题标题】:Using instantiated class members as variables in abstract class methods在抽象类方法中使用实例化的类成员作为变量
【发布时间】:2016-11-23 19:19:50
【问题描述】:

我正在尝试弄清楚如何在基本抽象类中创建一个能够使用从该类派生的实例化对象的成员值的方法。例如,假设我有一个名为 Vehicle 的类,它继承了一个名为 IVehicle 的接口;

public abstract class Vehicle : IVehicle
{
    public int Wheels = 4;

    public int CountWheels()
    {
        return Wheels;
    }
}

假设我有另一个名为Motorcycle 的类继承Vehicle

public class Motorcycle : Vehicle, IVehicle
{
    public int Wheels = 2;
}

如果我创建一个名为newMotorcycle 的新Motorcycle 并调用newMotorcycle.CountWheels(),我会得到4 而不是2。我假设这是WheelsMotorcycle 类中定义的问题,但我已经尝试了我能想到的所有方法来让它工作,它似乎总是想忽略子类定义。我知道我可以将CountWheels() 方法抽象化并在Motorcycle 类中定义它,但我试图使基本Vehicle 类尽可能通用,这样我就可以实现大量其他子类而无需不得不一遍又一遍地重新定义相同的方法。

我的第一个问题;我想要做的甚至可能吗?如果是这样,我的成员定义的哪一部分需要更改才能按我的预期方式工作?

我保证在我在这里发布之前我已经搜索了互联网,但我找不到足够的信息来帮助自己......

【问题讨论】:

  • 为什么需要轮子和 countWheels?你可以例如在 Vehicle.countWheels 中返回 4 作为默认值,然后覆盖 Motorcycle.countWheels 并返回 2。然后移除车轮。只是一个例子......
  • @ElDuderino 有人可以推测这是一个 MCVE,而且他的真实代码不那么做作

标签: c# class inheritance abstract


【解决方案1】:

您会注意到您发布的代码中有一条警告:

Motorcycle.Wheels 隐藏继承的成员 Vehicle.Wheels...

因此您的问题是,Vehicle 不知道派生类隐藏其中一个成员(因此为什么隐藏是个坏主意)。

既然你不能有虚拟字段,你应该把它改成虚拟的(或者在这种情况下,抽象,所以每个人都必须定义它)属性

public abstract class Vehicle : IVehicle
{
    public abstract int Wheels {get;}

    public int CountWheels()
    {
        return Wheels;
    }
}

public class Motorcycle : Vehicle, IVehicle
{
    public int Wheels => 2;
}

现在每个派生类都必须有一个基类可以使用的Wheels 属性。

【讨论】:

  • 我很感激。我注意到了警告并试图纠正它,但以错误的方式去做。感谢您的快速响应!
【解决方案2】:

您需要将Wheels 成员设为virtualoverride,否则您只是在“隐藏”基本成员。您还需要将其更改为属性才能使其成为virtual

public abstract class Vehicle 
{
    public virtual int Wheels { get { return 4; } }

    public int CountWheels()
    {
        return Wheels;
    }
}

public class Motorcycle : Vehicle
{
    public override int Wheels { get { return 2; } }
}

【讨论】:

    【解决方案3】:

    查找virtual属性和方法(https://msdn.microsoft.com/en-us/library/9fkccyh4.aspx

    您需要 Wheels 是基数的 public virtual int Wheels {get; set;} 和派生的 public override int Wheels {get; set;}

    然后你可以在每个类中根据需要初始化值。

    【讨论】:

      【解决方案4】:

      这是另一种选择。与其将Wheels 定义为Vehicle 上的虚拟属性并覆盖Motorcycle 上的该属性,不如将Wheels 定义为普通属性,然后在Motorcycle 的构造函数中设置它:

      public abstract class Vehicle : IVehicle
      {
          public int Wheels { get; protected set; }
      
          public Vehicle()
          {
              Wheels = 4;
          }
      
          public int CountWheels()
          {
              return Wheels;
          }
      }
      
      public class Motorcycle : Vehicle, IVehicle
      {
          public Motorcycle()
          {
              Wheels = 2;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2019-02-11
        • 2015-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-10
        • 2021-01-08
        • 2017-02-05
        相关资源
        最近更新 更多