基类A包含基类B属性,但派生类A1包含派生类B1

时间:2014-09-22 00:00:35

标签: c# oop

我有以下真实世界模式,其中基类BCA拥有基类类型B的公共属性BCBBCABCB都分别有两个派生类 - DCA1DCA2DCB1DCB2。在DCA1DCA2中的每一个中,真实世界中的属性实际上分别为DCB1DCB2类型。

如何最有效地将其转换为代码 - OOP设计?我将B保留在BCA中,还是应该在DCA1DCA2的每一个中进行具体输入?我应该使用泛型吗?这个设计有什么问题吗?碰巧我在这个项目中已经遇到过几次,不知怎的,它感觉不对;但我想知道我的观念是否错误。

修改 我给出了一个更具体的例子,使其更清晰。我很抱歉,但我不允许发布图像以在类图上显示它,但这就是它:

宠物具有PetFood类型的DailyMeal属性。 Cat的DailyMeal属性为CatFood类型,Dog's DailyMeal属于DogFood类型。

我希望这会使模式更清晰。

EDIT2: 这个问题重新表达为:你如何模拟这样一个真实世界的场景,你有一个带引擎的汽车,带有ElectricEngine的ElectricCar和带柴油发动机的柴油车等,以OOP术语,特别是C#,所以你可以使用多态:

Car myCar = myElectricCar;

myCar.Engine = myElectricEngine;

等,同时确保每种Car类型都具有正确的引擎类型。目标是根据类,接口和/或泛型或其他任何方面对这个真实场景进行建模,并获得OOP的全部好处。

2 个答案:

答案 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不能是多态的。