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

发布于 2024-07-17 10:05:26 字数 627 浏览 6 评论 0原文

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

谢谢

This may be a beginner question but is there a standard way to refactor the duplication of the Wheel property into the abstract class yet still maintain the explicit cast to the Part type. Let’s assume we have to prevent a FastCarWheel from being put on a SlowCar, and that there are many properties just like this one.

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

In this type of scenario is it common to just allow this type of duplication? I was thinking of making use of Generics but it just seems like I’m moving the issue around, and it gets worse for each additional property that behaves this way.

abstract class Car <P>
    where P : Part
{
    protected abstract P Wheel { get; set; }
}

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

前事休说 2024-07-24 10:05:26

我认为使用 FastSlow 策略 可以帮助为给定的汽车类型安装正确的车轮(其中 CarWheel 都依赖于政策和 Car比如说,对象有一个私人的轮子集合)。

I think using a Fast or Slow policy can help put the correct wheel for a given car type (where both Car and Wheel are dependent on the policy and a Car object has, say, a private aggregration of wheels).

眼趣 2024-07-24 10:05:26

此解决方案不是多态的,但如果您需要基类级别的可见性,则可能是您唯一的选择:

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

您可能想要评估您的基类是否做得太多。 通过将您的班级分成许多较小的班级,也许可以解决您的问题。 另一方面,有时这是不可避免的。

This solution isn't polymorphic, but might be your only option if you need visibility at the base class level:

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

You might want to evaluate if your base class is doing too much. It might be possible to solve your problem by splitting your classes in to many smaller classes. On the other hand, sometimes it's unavoidable.

提笔落墨 2024-07-24 10:05:26

由于您的目标似乎是允许客户端代码将属性作为 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 基类,恕我直言,这是一个更好的解决方案。

Since your goal appears to be allowing the client code to get the property back as a WheelPart, but only set it as a specific subclass you have a couple of options. Though I'm afraid that neither of them are very clean.

Firstly you could throw a runtime error if the wrong type is set:

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

But I wouldn't do this as it is very unclear to the client code that any other type of wheel will throw an exception, and they'll get no compiler feedback.

Otherwise you could separate out the Getter and Setter for the property so that the type required is very clear:

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

This is much clearer to the client and IMHO a nicer solution if you absolutely must expose the getter as the base WheelPart class.

兲鉂ぱ嘚淚 2024-07-24 10:05:26

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

I would create an ICar and then define your Cars that way, instead of an abstract class

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 {}
山人契 2024-07-24 10:05:26

定义车轮接口 (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();

Define a wheel interface (IWheel):

public interface IWheel
{
}

Implement the interface for FastCarWheel and SlowCarWheel eg

public class FastCarWheel : IWheel
{
}

Now your abstract class becomes:

abstract class Car 
{
 public IWheel Wheel { get; set; }
}

Subclasses of Car are then free to use whatever implementation of Wheel they choose:

FastCar fastCar = new FastCar();
fastCar.Wheel = new FastCarWheel();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文