关于重构为抽象类的基本问题

时间:2009-04-23 18:11:50

标签: c# inheritance abstract-class

这可能是一个初学者的问题,但是有一种标准的方法可以将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; }
}

由于

5 个答案:

答案 0 :(得分:1)

我认为使用FastSlow policy可以帮助为给定的汽车类型设置正确的轮子(CarWheel都依赖于关于策略和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();