2

我有一个关于技术和实现的问题,而不是要解决的实际问题。最近我创建了一个抽象类,我们称之为A,它定义了它的子类的共同行为。

我用它来构造几个子类 B、C 和 D,然后将它们传递给超类-子类结构之外的其他方法,该结构采用类型 A(因此能够处理所有 B、C 和 D)。

在 Java 中,我使用 instanceof 来检索真实类型,但最终我不得不对真实类型进行大量转换,而且看起来很乱。有人对如何使代码更干净有任何建议吗?

我尝试的一种方法是从超类的参数中重构子类类型的实例,这样我就可以使用它的实际类型来处理对象,从而避免类型转换。由于这些子类中的每一个都是单例(是的,它们保持状态),所以我觉得这样做没问题。这似乎是一件糟糕的事情吗?

感谢任何回答的人,非常感谢!

编辑:我用斜体添加了进一步的说明。谢谢。

4

4 回答 4

3

如果您需要检查类型,我不明白为什么要让它们从基类继承。抽象类/接口 A 定义了 B、C 和 D 应该实现的一系列函数,然后接受 A 实例的函数应该只调用这些抽象函数。如果您需要调用仅 B 包含的函数(因此不会被覆盖),那么您的函数应该采用 B 而不是 A 的实例。

还是我完全错过了重点?今天早上我没有喝咖啡因。

于 2009-07-16T13:44:14.640 回答
3

泛型是用来处理这个问题的。

考虑以下示例:

public class SuperClass<T extends SuperClass> {

     public abstract void someMethod(T param);

}


public class SubClassA extends SuperClass<SubClassA> {

    public void someMethod(SubClassA param) {}
}

编辑:鉴于评论,我会说那是一种设计气味。整个其他类要么需要子类来关联(此时可以应用相同的技术),要么涉及其他一些设计问题。在一个类上有一个方法,它接受一个不同类的超类,然后继续关心子类型,这很奇怪。

如果这是您需要的,您可以简单地通过方法重载来完成此操作。考虑:

  public void someMethod(SuperClass param) {
      if (param instanceof SubClassA) {
         someMethod((SubClassA) param);
      } else if (param instanceof SubClassB) {
         someMethod((SubClassB) param);
      }
  }

  public void someMethod(SubClassA param) {}

  public void someMethod(SubClassB param) {}

但这并没有让你摆脱 if 陷阱。这取决于有多少以及它们的不稳定程度,看看这里是否值得使用更重的解决方案。

于 2009-07-16T13:33:28.587 回答
0

听起来您想要访问者模式。就我个人而言,我不是一个忠实的粉丝,但它的工作原理如下:

class A { abstract void visit(MyVisitor visitor); }

这必须在每个子类中实现:

class B extends A { 
    public void visit(MyVisitor v) { v.visit(this); }
}

所以实际的访问者使用重载如下:

interface MyVisitor {
   public void visit(B b);
   public void visit(C c);
}

现在您可以实现您的访问者并调用visit您的 A 实例。然后将调用正确的回调方法:

A a = new B();
a.visit(this);

假设this实例实现MyVisitor,这将导致方法上的visit(B)回调

于 2009-07-16T14:25:12.647 回答
0

正如一晒所说,它看起来像一种设计气味。如果你有 instanceof-s,它会修改你的方法的行为,那么你就走错了路。考虑将此行为移到 A 类的继承者中。

除此之外,您可以使用泛型来参数化 A 类。这是一个代码示例

abstract class A<T extends A>{
   abstract protected void someMethod(T value);
}

class B extends A<B>{
    protected void someMethod(B value) {
    }
}

class C extends A<C>{
    protected void someMethod(C value) {
    }
}
于 2009-07-16T15:47:38.423 回答