这可能是一个初学者的问题,但是有一种标准的方法可以将Wheel属性的重复重构为抽象类,但仍然保持对Part类型的显式强制转换。我们假设我们必须阻止将FastCarWheel放在SlowCar上,并且有许多属性就像这样。
abstract class Car {}
class FastCar : Car
{
public FastCarWheel Wheel { get; set; }
}
class SlowCar : Car
{
public SlowCarWheel Wheel { get; set; }
}
abstract class WheelPart {}
class FastCarWheel: WheelPart {}
class SlowCarWheel: WheelPart {}
在这种情况下,只允许这种类型的复制是常见的吗?我正在考虑使用泛型,但似乎我正在解决这个问题,而且每个额外的属性都会变得更糟。
abstract class Car <P>
where P : Part
{
protected abstract P Wheel { get; set; }
}
由于
答案 0 :(得分:1)
我认为使用Fast
或Slow
policy可以帮助为给定的汽车类型设置正确的轮子(Car
和Wheel
都依赖于关于策略和Car
对象,例如,私人聚合轮子。)
答案 1 :(得分:1)
此解决方案不是多态的,但如果您需要基类级别的可见性,则可能是您唯一的选择:
abstract class Car
{
private CarWheel wheel;
public CarWheel Wheel
{
get { return wheel; }
protected set { wheel = value; }
}
}
class FastCar : Car
{
public new FastCarWheel Wheel
{
get { return base.Wheel as FastCarWheel; }
set { base.Wheel = value; }
}
}
class SlowCar : Car
{
public new SlowCarWheel Wheel
{
get { return base.Wheel as SlowCarWheel ; }
set { base.Wheel = value; }
}
}
您可能想要评估您的基类是否做得太多。通过将类拆分为许多较小的类,可能可以解决您的问题。另一方面,有时它是不可避免的。
答案 2 :(得分:1)
我会创建一个ICar,然后以这种方式定义你的汽车,而不是抽象类
interface ICar
{
IWheel Wheel {get; set;}
}
class FastCar: ICar
{
FastWheel fastWheel;
IWheel Wheel
{
get { return fastWheel; }
set
{
if (value is FastWheel) fastWheel = (FastWheel)value;
}
}
}
class SlowCar: ICar
{
SlowWheel slowWheel;
IWheel Wheel
{
get { return slowWheel; }
set
{
if (value is SlowWheel ) slowWheel = (SlowWheel )value;
}
}
}
class FastWheel: IWheel {}
class SlowWheel: IWheel {}
答案 3 :(得分:1)
由于您的目标似乎是允许客户端代码将属性作为WheelPart返回,但只将其设置为特定的子类,您有几个选项。虽然我担心它们都不是很干净。
首先,如果设置了错误的类型,您可能会抛出运行时错误:
public abstract class Car
{
public abstract WheelPart Wheel { get; set; }
}
public class FastCar : Car
{
private FastWheel _wheel;
public override WheelPart Wheel
{
get { return _wheel; }
set
{
if (!(value is FastWheel))
{
throw new ArgumentException("Supplied wheel must be Fast");
}
_wheel = (FastWheel)value;
}
}
}
但我不会这样做,因为客户端代码很不清楚任何其他类型的轮子会抛出异常,并且它们不会得到编译器反馈。
否则你可以将属性的Getter和Setter分开,以便所需的类型非常清楚:
public abstract class Car
{
public abstract WheelPart Wheel { get; }
}
public class FastCar : Car
{
private FastWheel _wheel;
public override WheelPart Wheel
{
get { return _wheel; }
}
public void SetWheel(FastWheel wheel)
{
_wheel = wheel;
}
}
如果您绝对必须将getter公开为基础WheelPart类,那么对于客户端和IMHO来说这是一个更好的解决方案。
答案 4 :(得分:0)
定义滚轮界面(IWheel):
public interface IWheel
{
}
实现FastCarWheel和SlowCarWheel的接口,例如
public class FastCarWheel : IWheel
{
}
现在你的抽象类变为:
abstract class Car
{
public IWheel Wheel { get; set; }
}
Car的子类随后可以自由使用他们选择的任何Wheel实现:
FastCar fastCar = new FastCar();
fastCar.Wheel = new FastCarWheel();