gpt4 book ai didi

c# - 从抽象基类返回规范表示子类是否可以接受?

转载 作者:行者123 更新时间:2023-11-30 15:17:16 25 4
gpt4 key购买 nike

编辑 2: TL;DR : 有没有办法不打破面向对象的最佳实践,同时仍然满足一堆同类事物必须可以转换为那种规范事物的约束?

另外,请记住,我的问题是关于一般情况,而不是具体示例。这不是家庭作业的问题。

假设您有以下内容:

  • 一个实现通用功能的抽象基类;
  • 一个具体的派生类,用作规范表示。

  • 现在假设您希望基类的任何继承者都可以转换为规范表示。这样做的一种方法是在基类中有一个抽象方法,该方法旨在将继承者的转换返回为规范派生类的实例。

    然而,似乎普遍接受的是基类不应该知道它们的任何派生类,在一般情况下,我同意。然而,在这种情况下,这似乎是最好的解决方案,因为它支持任意数量的派生类,每个派生类都有自己的实现,我们不需要知道任何事情,通过转换为每个派生的规范表示可以互操作类必须实现。

    你会做不同的事情吗?为什么以及如何?

    几何点的示例:
    // an abstract point has no coordinate system information, so the values
    // of X and Y are meaningless
    public abstract class AbstractPoint {
    public int X;
    public int Y;

    public abstract ScreenPoint ToScreenPoint();
    }

    // a point in the predefined screen coordinate system; the meaning of X
    // and Y is known
    public class ScreenPoint : AbstractPoint {
    public ScreenPoint(int x, int y) {
    X = x;
    Y = y;
    }

    public override ScreenPoint ToScreenPoint()
    => new ScreenPoint(X, Y);
    }

    // there can be any number of classes like this; we don't know anything
    // about their coordinate systems and we don't care as long as we can
    // convert them to `ScreenPoint`s
    public class ArbitraryPoint : AbstractPoint {
    private int arbitraryTransformation;

    public ArbitraryPoint(int x, int y) {
    X = x;
    Y = y;
    }

    public override ScreenPoint ToScreenPoint()
    => new ScreenPoint(X * arbitraryTransformation, Y * arbitraryTransformation);

    // (other code)
    }

    编辑 1: AbstractPointScreenPoint 不是同一个类的原因是语义。 AbstractPoint 没有定义的坐标系,因此 AbstractPoint 实例中 X 和 Y 的值是没有意义的。 ScreenPoint 确实具有定义的坐标系,因此 ScreenPoint 实例中的 X 和 Y 值具有明确定义的含义。

    如果 ScreenPoint 是基类,那么 ArbitraryPoint 将是 ScreenPoint ,事实并非如此。 ArbitraryPoint 可以转换为 ScreenPoint ,但这并不意味着它 is-a ScreenPoint

    如果您仍然不相信,请考虑可以将任意坐标系 ACS1 定义为对屏幕坐标系 SCS 具有动态偏移量。这意味着两个坐标系之间的映射可以随时间变化,即点 ACS1 (1, 1) 可以在某一时刻映射到 SCS (10, 10),而在另一时刻映射到 SCS (42, 877)

    最佳答案

    这种设计通常是代码异味。基类不应该知道它们的派生类,因为它会创建循环依赖。循环依赖通常会导致复杂的设计,在这种情况下很难推断类应该做什么。在 Java 中,基类知道它们的派生类甚至会在极少数情况下导致死锁(我不知道 C#)。

    但是,您可以在特殊情况下打破一般规则,当您确切地知道自己在做什么时,特别是如果您要实现的目标足够简单。

    你的情况似乎很简单。将 AbstractPointScreenPoint 作为不同的类是正确的。但实际上它们“一起工作”:所有 AbstractPoint 都应该能够转换为 ScreenPoint (这可能是 AbstractPoint 契约(Contract)中最重要的功能?)。由于没有另一个就不能存在,因此 AbstractPoint 了解 ScreenPoint 并没有错。

    更新

    在不同的设计中:创建一个名为 CanonicalPoint 的接口(interface)。AbstractPoint 有一个名为 ToCanonicalPoint 的方法,它返回 CanonicalPointAbstractPoint 的所有派生类都必须实现它并返回 CanonicalPointScreenPointAbstractPoint 的派生类,它实现了 CanonicalPoint 接口(interface)。
    您甚至可以拥有多个实现 CanonicalPoint 的派生类。
    注意:如果 AbstractPointCanonicalPoint 有共同的方法,两者都可以实现另一个
    称为 Pointable 的接口(interface),它声明了所有这些方法。

    关于c# - 从抽象基类返回规范表示子类是否可以接受?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46985824/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com