3

我有很多课程,请允许我介绍它们,然后在最后问我的问题:

我有一个容器类,其中包含复合关系中的两个对象:

public class Container{

    A a;
    B b;

    public someMethod(){
        a.getC().myMethod(b);
    }
}

A 和 B 是超类(或接口),其子类型也可以是复合关系中的类型。

A 包含(接口)类型 C 的成员:

public class A{
   C c;
}


public interface C{
    public void myMethod(B b);
}

public class D implements C{
    public void myMethod(B b){
        //This code will modify the state of object b, in class Container.
        b.changeState();
    }
}

public class E implements C{
    public void myMethod(B b){
        //This code will modify the state of object b, in class Container.
        b.changeState();
    }
}

我的问题是我希望将对象 b 的状态从容器类中开始的方法修改为类 D 和 E——通过动态绑定调用 myMethod(),该方法最终调用层次结构中的代码。我想这样做是因为我将使用多态性来运行正确的myMethod()(取决于对象的类型是 D 还是 E)并且我希望这样做,而不是编写 IF 语句。

所以我的问题是,将对象 b 的实例沿类层次结构向下传递给 myMethod 似乎非常糟糕,这样我就可以运行特定于 b 的代码来修改 b 的状态。我还能做些什么来从 d 和 e (统称为 c)修改 b 吗?

我可以只使用接口而不使用泛型来让它工作——但是当我添加泛型时,我遇到了类型问题,这让我开始思考我的整个设计是否有缺陷?

编辑:我可以通过使用 IF 语句轻松地做到这一点 - 但我想要一个使用 D 和 E 类的多态性的优雅解决方案。

4

2 回答 2

2

首先,如果我正确理解了您的问题,那么B您的代码中没有任何实例被“传递”。动态调度将简单地导致myMethod()实际类型的实现被作为参数a的实例调用。B

虽然每次实现时都必须显式地编写参数可能很乏味,myMethod()但这并没有错。

另一种方法是给每个子类/实现Atype 的属性B。但是,在这种情况下,您必须将B实例沿着构造函数链传递给实际具有您的B属性的类。

您的代码将变为:

public class A{
  C c;

  public A(C c) {
    this.c = c;
}


public interface C{
    public void myMethod(B b);
}

public abstract class CC {
  protected B b;

public CC(B b) {
  this.b = b;

public class D extends CC implements C {
    public D(B b) {
      super(b);
    }
    public void myMethod(){
        b.changeState();
    }
}

public class E extends CC implements C {
    public E(B b) {
      super(b);
    }
    public void myMethod(){
        b.changeState();
    }
}

然后在某个地方,例如在Container的构造函数中:

b = new B();
a = new A(new E(b));
于 2012-07-12T20:35:33.543 回答
0

您可以将 B 的实例传递给 E 的构造函数(或使用 setter)。这本身就带来了问题,但至少它避免了每次调用 myMethod() 时都必须向下传递 B,而现在不需要参数。

例如

B里面的某个地方

E myE = new E(this);

并且,在 E 内

final B myB;
public E(B myHigherLevelThing) {
  this.myB = myHigherLevelThing;
}

public void myMethod() {
  myB.changeState();
}

使用最通用的声明界面,我对你的完整层次结构有点困惑,所以那里可能有改进的空间......

于 2012-07-12T20:30:58.580 回答