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」という 2 つの抽象クラスを作成する方法もありますが、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なように思えます。VehicleSteeringWheelSize

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があります。ハンドルがないため、モデルが適合しなくなります。Bikeaと a の両方をモデル化できるようにしたい場合はCar、おそらく と の間に別のクラスが必要であり、代わりにメンバーを配置するVehicleと、代わりにそれが渡されます。(これは実質的に MarcinJuraszek の答えですが、新しい中間クラスに、上記のようにハンドルのサイズを受け入れるコンストラクターを提供します。)CarSteeringWheelSizeFourWheelTransmission

これは、継承のワンショットを使い果たすという点で少し厄介です。つまり、「ハンドルがあるかどうか」が 1 つの重要な違いであると効果的に判断していることになります。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 ISteerableFourWheelTransmissionFourWheelTransmissionFourWheelTransmissionVehicleISteerableIVehicle

また、これにはパブリック フィールドではなくプロパティを使用する必要があることに注意してください。インターフェイスではフィールドを指定できません。いずれにせよ、これは良いことだと思います。パブリック API を介して実装の詳細を公開しているため、パブリック フィールドは非常に嫌いです。

于 2013-06-20T05:53:27.783 に答える
0

1 つの簡単な解決策は次のとおりです。

二輪車のステアリング サイズにもデフォルト値を指定し (-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 に答える