写真がなければ、サブクラスによって呼び出され、コンストラクターで値が割り当てられる が必要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
があります。ハンドルがないため、モデルが適合しなくなります。Bike
aと a の両方をモデル化できるようにしたい場合はCar
、おそらく と の間に別のクラスが必要であり、代わりにメンバーを配置するVehicle
と、代わりにそれが渡されます。(これは実質的に MarcinJuraszek の答えですが、新しい中間クラスに、上記のようにハンドルのサイズを受け入れるコンストラクターを提供します。)Car
SteeringWheelSize
FourWheelTransmission
これは、継承のワンショットを使い果たすという点で少し厄介です。つまり、「ハンドルがあるかどうか」が 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
ISteerable
FourWheelTransmission
FourWheelTransmission
FourWheelTransmission
Vehicle
ISteerable
IVehicle
また、これにはパブリック フィールドではなくプロパティを使用する必要があることに注意してください。インターフェイスではフィールドを指定できません。いずれにせよ、これは良いことだと思います。パブリック API を介して実装の詳細を公開しているため、パブリック フィールドは非常に嫌いです。