代码之家  ›  专栏  ›  技术社区  ›  Boden

在没有RTTI或基类修改的情况下对基类或子类进行操作

oop
  •  1
  • Boden  · 技术社区  · 17 年前

    我问a similar question yesterday 这是特定于一项技术的,但现在我发现自己在广义上对这个话题感到疑惑。

    为了简单起见,我们有两个类,A和B,其中B从A派生而来。B确实是A,A中定义的所有例程在B中都有相同的含义。

    解决:

    1. 在a中提供一个B可以重写的display()方法。…但随后我们开始合并UI和模型。除非我没有看到什么很酷的把戏,否则我不会考虑这个。

    所以我想问题可能真的归结为:

    如果我有一个子类通过以下方式扩展基类 当我们试图对一组可能是a或B的对象采取行动时,一切似乎都会立即崩溃。

    3 回复  |  直到 9 年前
        1
  •  2
  •   itowlson    17 年前

    然而,考虑到你更一般的问题,即“我们如何处理 额外 我们不能或不允许通过基类以多态方式访问的行为,“例如,如果基类不在我们的控制之下,你的选项可能是选项3、访问者模式或辅助类。在这两种情况下,你都是在将多态性有效地外包给外部实体——在选项3中,UI(例如呈现者或控制器),它执行instanceOf检查,并根据是否是B执行不同的操作;在访问者或辅助者的情况下,是新类。以你的例子为例,访问者可能是矫枉过正的(而且,如果你不能/不愿意更改基类来适应它,我认为不可能实现它),所以我建议使用一个名为“renderer”的简单类:

    public abstract class Renderer {
      public static Renderer Create(A obj) {
        if (obj instanceOf B)
          return new BRenderer();
        else
          return new ARenderer();
      }
    
      public abstract Color getColor();
    }
    
    // implementations of ARenderer and BRenderer per your UI logic
    

    这封装了运行时类型检查,并将代码捆绑到具有明确职责的合理定义良好的类中,而没有Visitor的概念开销。(不过,根据GrizzlyNyo的回答,如果你的层次结构或功能集比你在这里展示的更复杂,那么Visitor可能更合适,但许多人发现Visitor很难理解,我倾向于在简单的情况下避免使用它——但你的里程可能会有所不同。)

        2
  •  1
  •   Community Mohan Dere    9 年前

    给出的答案是 itowlson 很好地涵盖了问题的大部分。我现在将尽可能简单地处理最后一段。

    继承应该实现重用,以便在旧代码中重用你的派生类,而不是让你的类重用基类的一部分(你可以使用聚合)。

    itowlson

    如果你最终要求使用代码绕过类型系统,你的设计就会有一个奇怪的地方 smell 当然,永远不要说永远不会,但你可以肯定地说:避免依赖 实例检查 或因逻辑而沮丧。

        3
  •  0
  •   Community Mohan Dere    9 年前

    这看起来像是访问者设计模式(也称为“双分派”)的教科书案例。

    this answer 获取有关访问者和复合模式的详细解释的链接。