Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 重构成抽象类的基本问题_C#_Inheritance_Abstract Class - Fatal编程技术网

C# 重构成抽象类的基本问题

C# 重构成抽象类的基本问题,c#,inheritance,abstract-class,C#,Inheritance,Abstract Class,这可能是一个初学者的问题,但是否有一种标准方法可以将Wheel属性的副本重构到抽象类中,同时仍然保持对零件类型的显式转换。让我们假设我们必须防止FastCarWheel被放在慢车上,并且有许多属性与此类似 abstract class Car {} class FastCar : Car { public FastCarWheel Wheel { get; set; } } class SlowCar : Car { public SlowCarWheel Wheel {

这可能是一个初学者的问题,但是否有一种标准方法可以将Wheel属性的副本重构到抽象类中,同时仍然保持对零件类型的显式转换。让我们假设我们必须防止FastCarWheel被放在慢车上,并且有许多属性与此类似

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; }
}
抽象类汽车

其中P:零件 { 受保护的抽象P轮{get;set;} }

感谢定义控制盘接口(IWheel):

实现FastCarWheel和SlowCarWheel的接口

public class FastCarWheel : IWheel
{
}
现在,您的抽象类变成:

abstract class Car 
{
 public IWheel Wheel { get; set; }
}
Car的子类可以自由使用他们选择的任何车轮实现:

FastCar fastCar = new FastCar();
fastCar.Wheel = new FastCarWheel();

我认为使用
Fast
Slow
有助于为给定的车型安装正确的车轮(其中
car
wheel
都取决于策略,而
car
对象具有私人车轮聚合),但如果您需要基类级别的可见性,则可能是您唯一的选择:

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; }
    }
}

您可能需要评估基类是否做得太多。通过将类拆分为多个较小的类,可以解决您的问题。另一方面,有时这是不可避免的。

我会创建一个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 {}

由于您的目标似乎是允许客户端代码将属性作为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公开为basewheelpart类,那么这对客户和IMHO来说是一个更好的解决方案。

这就是问题所在。他不希望任何汽车都有任何类型的轮子。他希望快车只有快轮,慢车只有慢跟。接口无法实现这一点。如果FastCar不能有一个SlowCarWheel,那么该逻辑属于FastCar,而不属于基类。我同意,但问题是您的代码会促进使用这个(FastCar.Wheel=new SlowCarWheel();),他明确表示不允许使用它。不过,我同意这种逻辑不属于基类。第二种解决方案似乎很好。
    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;
        }
    }