0

假设我有以下代码:

public abstract class Vehicle
{    
  public Transmission MyTransmission;
  public int NumberOfWheels;
  public int NumberOfSeats;
  public int Weight;
  public int TopSpeed; //etc.
}

public class Car : Vehicle
{
  public int SteeringWheelSize = 10;
}

public class Truck : Vehicle
{
  public int SteeringWheelSize = 20;
}

public class Bike : Vehicle
{

}

public class FourWheelTransmission
{
  public Vehicle ParentVehicle;
  public Transmission(Vehicle vehicle)
  {
    ParentVehicle = vehicle;
    //here, I want to access the SteeringWheelSize from its ParentVehicle object.
  }
}

要完成最后评论中的目标,最好的方法应该是什么?当然,一种方法是创建两个抽象类:“公共抽象类 TwoWheelVehicle”和“公共抽象类 FourWheelVehicle”,但是如果我们不想重复 FourwheelVehicle 和 TwoWheelVehicle 中常见的所有相似属性怎么办?允许 FourWheelTransmission 类访问其车辆的 SteeringWheelSize 的其他方式?

4

4 回答 4

3

那个怎么样:

public abstract class Vehicle
{    
  public Transmission MyTransmission;
  public int NumberOfWheels;
  public int NumberOfSeats;
  public int Weight;
  public int TopSpeed; //etc.
}

public abstract class FourWheelVehicle : Vehicle
{
  public int SteeringWheelSize;
}

public class Car : FourWheelVehicle
{
    public Car()
    {
        SteeringWheelSize = 10;
    }
}

public class Truck : FourWheelVehicle
{
    public Truck()
    {
        SteeringWheelSize = 20;
    }
}


public class FourWheelTransmission
{
  public FourWheelVehicle ParentVehicle;
  public Transmission(FourWheelVehicle vehicle)
  {
    ParentVehicle = vehicle;
    //here, I want to access the SteeringWheelSize from its ParentVehicle object.
  }
}
于 2013-06-20T05:53:09.187 回答
2

如果没有Bike在图片中,在我看来Vehicle应该有一个SteeringWheelSize在构造函数中分配了一个值,由子类调用。

public abstract class Vehicle
{
    public int SteeringWheelSize { get; private set; }
    ...

    protected Vehicle(int steeringWheelSize)
    {
        SteeringWheelSize = steeringWheelSize;
    }
}

public class Car : Vehicle
{
    public Car() : base(20)
    {
    }
}

...

但是,您现在有一个问题:Bike没有方向盘,因此您的模型不再适合。如果您希望能够对 aBike和 a进行建模,您可能需要在andCar之间建立另一个类,然后将成员放在那里——然后将其传递给它。(这实际上是 MarcinJuraszek 的回答,尽管我会给新的中间类一个构造函数,接受上述方向盘尺寸。)VehicleCarSteeringWheelSizeFourWheelTransmission

就用完一次继承而言,这有点尴尬——你实际上是在决定“它是否有方向盘”是一个重要的区别;由于 C# 中缺少实现的多重继承,因此您无法以相同的方式在其他地方做出不同的区分。

或者,两者都Car可以Truck实现一个接口,说明他们有一个方向盘,并且FourWheelTransmission可以使用它来代替。那时您仍然可以使用中间抽象类,但您不必:

public interface ISteerable
{
    int SteeringWheelSize { get; }
}

public abstract class Vehicle
{
    // Properties here
}

public class Car : Vehicle, ISteerable
{
    public SteeringWheelSize { get { return 20; } }
}

...

public class FourWheelTransmission
{
    // We know we can safely cast this to ISteerable
    private Vehicle vehicle;

    private FourWheelTransmission(Vehicle vehicle)
    {
        this.vehicle = vehicle;
    }

    public static FourWheelTransmission<T> FromSteerableVehicle(T vehicle)
        where T : Vehicle, ISteerable
    {
    }
}

请注意这里的轻微尴尬 - 我们无法向编译器表示FourWheelTransmission将具有单个变量,该变量既是 的子类Vehicle 是 的实现ISteerable,除非我们使FourWheelTransmission自己成为通用的并使用约束。我在上面有一个解决方法,你只能基于这种类型构造一个实例,但不能是通用的。如果是一个接口,那么可以扩展.FourWheelTransmissionFourWheelTransmissionVehicleISteerableIVehicle

另请注意,这需要您使用属性而不是公共字段 - 接口不能指定字段。无论如何,我认为这是一件好事——我非常不喜欢公共领域,因为它们通过公共 API公开了实现细节。

于 2013-06-20T05:53:27.783 回答
0

一个简单的解决方案是:

您也可以为两轮车转向尺寸提供默认值(例如 -1),并在使用转向尺寸的逻辑中使用 if 条件。

于 2013-06-20T05:56:40.377 回答
0

我会创建一个界面。

public abstract class Vehicle {    
  public Transmission MyTransmission  { get; set; }
  public int NumberOfWheels { get; set; }
  public int NumberOfSeats { get; set; }
  public int Weight { get; set; }
  public int TopSpeed { get; set; } //etc.
}

public interface ISteeringWheelVehicle {
    int SteeringWheelSize { get; set; }
}

public class Car : Vehicle, ISteeringWheelVehicle {
    public Car() {
        SteeringWheelSize = 10;
    }

    public int SteeringWheelSize { get; set; }
}

public class Truck : Vehicle, ISteeringWheelVehicle {
    public Truck() {
        SteeringWheelSize = 20;
    }

    public int SteeringWheelSize { get; set; }
}

public class Bike : Vehicle {
}

public class FourWheelTransmission {
    public Vehicle ParentVehicle;
    public Transmission(Vehicle vehicle) {
        ParentVehicle = vehicle;

        if (ParentVehicle is ISteeringWheelVehicle) {
            var steeringWheelSize = ((ISteeringWheelVehicle)ParentVehicle).SteeringWheelSize;
        }
    }
}
于 2013-06-20T05:57:34.493 回答