我有以下真实世界模式,其中基类BCA
拥有基类类型B
的公共属性BCB
。 BCA
和BCB
都分别有两个派生类 - DCA1
和DCA2
,DCB1
和DCB2
。在DCA1
和DCA2
中的每一个中,真实世界中的属性实际上分别为DCB1
和DCB2
类型。
如何最有效地将其转换为代码 - OOP设计?我将B
保留在BCA
中,还是应该在DCA1
和DCA2
的每一个中进行具体输入?我应该使用泛型吗?这个设计有什么问题吗?碰巧我在这个项目中已经遇到过几次,不知怎的,它感觉不对;但我想知道我的观念是否错误。
修改 我给出了一个更具体的例子,使其更清晰。我很抱歉,但我不允许发布图像以在类图上显示它,但这就是它:
宠物具有PetFood类型的DailyMeal属性。 Cat的DailyMeal属性为CatFood类型,Dog's DailyMeal属于DogFood类型。
我希望这会使模式更清晰。
EDIT2: 这个问题重新表达为:你如何模拟这样一个真实世界的场景,你有一个带引擎的汽车,带有ElectricEngine的ElectricCar和带柴油发动机的柴油车等,以OOP术语,特别是C#,所以你可以使用多态:
Car myCar = myElectricCar;
myCar.Engine = myElectricEngine;
等,同时确保每种Car类型都具有正确的引擎类型。目标是根据类,接口和/或泛型或其他任何方面对这个真实场景进行建模,并获得OOP的全部好处。
答案 0 :(得分:0)
使用泛型。在其属性类型中使BCA通用,并将其约束为从BCB派生:
class BCA<T> where T: BCB
{
public T prop {get; set;}
}
答案 1 :(得分:0)
让我们使用以下示例:所有汽车都有发动机,但电动汽车有电动发动机。
你不能用类来设计它,但你可以使用协变接口:
interface ICar<out TEngine>
{
TEngine Engine { get; }
}
class Engine { }
class Car : ICar<Engine>
{
private readonly Engine engine;
public Car(Engine engine)
{
this.engine = engine;
}
public Engine Engine { get { return this.engine; } }
}
class ElectricEngine : Engine { }
class ElectricCar : ICar<ElectricEngine>
{
private readonly ElectricEngine engine;
public Car(ElectricEngine engine)
{
this.engine = engine;
}
public ElectricEngine Engine { get { return this.engine; } }
}
请注意,ElectricCar不会从Car继承。但是,ICar<ElectricEngine>
可分配给ICar<Engine>
,因此可行:
ICar<Engine> myCar = new ElectricCar(new ElectricEngine());
当然,您还可以定义一个非通用接口ICar,它包含与引擎无关的所有属性和方法。
请注意ICar<out TEngine>
是协变的。它也不能逆变。这意味着Engine属性必须是只读的。
<强>更新强>
你问为什么这个属性必须是只读的,以及它是否可写是一个固有的错误。嗯,是的。请考虑以下情况:
ICar<Engine> myCar = new ElectricCar();
// assume ICar<Engine> has a writabel property Engine of type Engine
myCar.Engine = new DieselEngine();
Engine类型的可写属性必须允许最后一个语句。但是在运行时这当然不起作用,因为myCar恰好是一辆电动车,那些人不会使用DieselEngines。
我建议您阅读Liskov Substitution Principle。
ElectricCar
可以使用Engine
类型的可写ElectricEngine
属性,但它的setter不能成为ICar<TEngine>
接口的一部分。因此,属性的setter不能是多态的。