我正在创建一个类库,用于创建具有特定功能的其他应用程序。库应该实现所有具体功能,实现应用程序将向类添加特定的业务规则。通常,这是一些对象的简单表示:
在课程库中:
interface IWheel
{
int Radius { get; set; }
string Color { get; set; }
}
abstract class Wheel : IWheel
{
int Radius { get; set; }
string Color { get; set; }
}
interface ICar
{
string Color { get; set; }
List<IWheel> Wheels { get; set; }
}
abstract class Car : ICar
{
string Color { get; set; }
List<IWheel> Wheels { get; set; }
public Car()
{
List<IWheel> Wheels = new List<IWheel>();
}
}
实施应用程序业务逻辑:
class SpecialWheel : Wheel
{
int SpecialWheelProperty { get; set; }
}
class SpecialCar : Car
{
string SpecialCarProperty { get; set; }
}
在实现应用程序实例化时:
SpecialWheel wheel1 = new SpecialWheel { SpecialWheelProperty = 6 };
SpecialWheel wheel2 = new SpecialWheel { SpecialWheelProperty = 6 };
SpecialWheel wheel3 = new SpecialWheel { SpecialWheelProperty = 8 };
SpecialWheel wheel4 = new SpecialWheel { SpecialWheelProperty = 8 };
SpecialCar car = new SpecialCar();
car.Wheels.Add(wheel1);
car.Wheels.Add(wheel2);
car.Wheels.Add(wheel3);
car.Wheels.Add(wheel4);
到目前为止一切都很好,直到我尝试做类似的事情:
// Cant do this as "SpecialWheelProperty" is not in the Interface contract
int wheelSpecialProperty = car.Wheels.First().SpecialWheelProperty;
我当然可以添加&#34; SpecialWheelProperty&#34;到IWheel接口并使其成为Wheel类的抽象属性,但这将破坏我在派生类中实现业务逻辑的最终目标。
我脑子里浮现了一些想法(也许是泛型),但是,在这种情况下,最好的方法是什么,以及这种方法的一个例子?
答案 0 :(得分:1)
问题是您的代码表示SpecialCar
和SpecialWheel
类之间没有关系,但期望SpecialCar
的接口公开SpecialWheel
个实例。您实际添加所有SpecialWheel
个实例的事实完全是巧合。
这似乎是泛型的任务,基类接受实现IWheel
的类型参数。
abstract class Car<TWheel> : ICar where TWheel : IWheel
{
string Color { get; set; }
ICollection<TWheel> Wheels { get; set; }
public Car()
{
Wheels = new List<TWheel>();
}
}
class SpecialCar : Car<SpecialWheel> {
// Whatever
}
现在你仍然可以做到这一点而不会失去任何类型的安全性:
int swp = car.Wheels.First().SpecialWheelProperty;
需要注意的是:虽然这种技术可以使您想要的代码成为可能,但如果在深层次结构中使用它,它很快就会失控。请谨慎使用。
答案 1 :(得分:0)
据我所知 SpecialWheel
是否存在业务逻辑,因此为了获得特定属性,似乎是正常的:
int wheelSpecialProperty = (car.Wheels.First() as SpecialWheel).SpecialWheelProperty;
一个问题:为什么要在中创建一个构造函数 汽车 既然它是抽象的?
答案 2 :(得分:0)
我认为,很难以一种精确的方式回答这个问题。问题是要了解你的系统。在这里,你只有我称之为&#34;技术&#34;。在这种情况下,继承和多态。但是当你构建系统时,它通常不止于此。如果您愿意,您可以拥有一个框架,管道,所有操作都在接口级别完成。工厂。然后,在专业领域,您可以使用以下特定于业务的代码:
class CarFactory
{
public static ICar BuildCar(int kind);
if (int == 0)
return new RegularCar();
else
return new SpecialCar();
}
所以在你的&#34; Special&#34;代码可以添加特殊属性值
SpecialCar sc = (SpecialCar)CarFactory.BuildCar(1); // notice casting
sc.SpecialProperty = "special value";
因此,只有特定的客户/消费者才会知道特殊属性。您的申请将与
一起运作ICar, IWheel, // etc
例如,当您获得普通汽车时,您的客户不知道1,只有0。
RegularCar rc = (RegularCar)CarFactory.BuildCar(0); // notice casting
但是调用&#34; AddWheels&#34;不知道它是什么车,并宣布为
CarBuilderWheelHandler.AddWheels(ICar c, List<IWheel> w)
CarBuilderWheelHandler
可能需要安装轮胎,给每个轮胎充气和平衡。但是你的特殊车轮可能安装了轮胎压力监测系统而不是常规阀门。在这种情况下,您的专用车有一个监控TPMS的设备,并知道如何处理特殊的车轮属性。但是当它从处理程序流向处理程序时,那些处理程序并不知道&#34;特殊的&#34;的东西。 Hadlers使用接口。
void AddWheels(ICar c, List<IWheel> w)
{
MountRubber(w);
Inflate(w);
Balance(w);
c.Wheels = w;
}
然后在特殊车内某处,它知道如何监控压力
void Timer_Tick(...)
{
foreach(SpecialWheel w in _wheels)
{
if w.Pressure < _pressureSetByDriver //'Pressure' is not part of IWheel
SendPressureWarningToDashboard();
}
}
这是一个非常抽象的例子,可能只对你有用,了解OOP中抽象对象的目的是什么。
我相信您的问题可以有很多答案,而且我们没有确切的工作环境