6

说我有班级签名

Class1(Class2 c);
Class2(Class1 c);

如何初始化两者?

4

2 回答 2

8

对于其中一个类,您无需在构造函数中提供引用,但您可以使用set- 方法。当它们以前都不存在时,初始化它们相互依赖似乎很困难。

class Foo {
    private Bar bar;
    public Foo(Bar bar) {
        this.bar = bar;
    }
}

class Bar {
    private Foo foo;
    setFoo(Foo foo) {
        this.foo = foo;
    }
}


Bar bar = new Bar();
Foo foo = new Foo(bar);
bar.setFoo(foo);

另请注意,可能有更好的解决方案。例如使用观察者模式,这完全取决于您计划如何使用您的对象。

于 2012-12-06T01:17:38.730 回答
5

你的问题没有多大意义。如果每个类都需要另一个类来初始化,那么你真的必须重新考虑你的类是如何设计的。

您可能会考虑让其中一个类自己创建另一个类,而不必在构造函数中指定它。例如 :

class Class1 {
    private Class2 c2;
    public Class1() {
        this.c2 = new Class2(this);
    }
}

class Class2 {
    private Class1 c1;
    public Class2(Class1 c) {
        this.c1 = c;
    }
}

或者创建设置器并允许它们在“未初始化”状态下创建(如果设置不正确,可能会引发异常)。例如 :

class Class1 {
    private Class2 c2;
    public void setClass2(Class2 c) {
        this.c2 = c;
    }
    public void doSomething() {
        if (null == c2) throw new IllegalStateException();
        // ...
    }
}

class Class2 {
    private Class1 c1;
    public void setClass1(Class1 c) {
        this.c1 = c;
    }
    public void doSomething() {
        if (null == c1) throw new IllegalStateException();
        // ...
    }
}

// somewhere else....
Class1 c1 = new Class1();
Class2 c2 = new Class2();
c1.setClass2(c2);
c2.setClass1(c1);

此外,如果每个实例都需要相互链接,您应该检查它们是否确实由正确的对象拥有,否则您可能会创建错误的引用......这正是为什么它首先是一个糟糕的设计地方。考虑一下:

Class2 c2 = new Class2(new Class1());

但是,您可能会认为这是一个聪明的构造c2.getClass1().getClass2() != c2

它也不能保证c1.getClass2() == c2 && c2.getClass1() == c1在上述两种情况下。

您的类应该检查反向引用是否正确,并且您无法使用任何一种方法正确实现这一点!

要解决这个先有鸡还是先有蛋的问题,您需要某种工厂方法或第三类。考虑一下:

abstract class Class1 {
    public abstract Class2 getClass2();
}

abstract class Class2 {
    public abstract Class1 getClass1();
}

public Class3 {
    private Class1 c1;
    private Class2 c2;
    public Class3() {
        c1 = new Class1_Impl();
        c2 = new Class2_Impl();
    }
    public Class1 getClass1() { return c1; }
    public Class2 getClass2() { return c2; }
    private class Class1_Impl extends Class1 {
         public Class1 getClass2() { return c2; }
    }
    private class Class2_Impl extends Class2 {
         public Class1 getClass1() { return c1; }
    }
}

// and later on...
Class3 c3 = new Class3();
Class1 c1 = c3.getClass1();
Class2 c2 = c3.getClass2();

有了这个,你就可以得到保证c1.getClass2() == c2 && c2.getClass1() == c1


如果你还在读书,那么你就在启蒙的轨道上。如果你能看到这个类设计的后果是什么,那么你就会明白循环依赖是一种反模式,应该避免。

但是,您的问题不够具体,我无法完全为您提供一种更正确的方法来以干净和更好的方式解决您的问题。

于 2012-12-06T01:28:05.657 回答