Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keep reference to new object passed into super constructor

Is there a good way to maintain a reference to an object created in a constructor that needs to be passed to the super constructor of some extended class (other than making it accessible from the super class or passing it into the constructor as a parameter)?

Let me clarify with an example. Take this class (which I can't modify and which doesn't give me access to foo):

class TestA {
    TestA(Object foo) {}
}

Now, I would like to extends this class as follows:

class TestB extends TestA {
    Object myCopyOfFoo;

    TestB() {
        super(new Object());
    }
}

Is there a good way to store the created new Object() in myCopyOfFoo?

Neither one of these three ideas work:

TestB() {
    myCopyOfFoo = new Object();
    super(myCopyOfFoo);
}

(Error: Constructor call must be the first statement in a constructor)

TestB() {
    super(myCopyOfFoo = new Object());
}

(Error: Cannot refer to an instance field myCopyOfFoo while explicitly invoking a constructor)

TestB() {
    super(makeFoo());
}

Object makeFoo() {
    myCopyOfFoo = new Object();
    return myCopyOfFoo;
}

(Error: Cannot refer to an instance method while explicitly invoking a constructor)

I guess I could do the following, but it's neither thread-safe nor elegant:

static Object tempFoo;

TestB() {
    super(tempFoo = new Object());
    myCopyOfFoo = tempFoo;
}

Does anyone have a better idea for me? And why on earth are my first two ideas not legit?

like image 324
Markus A. Avatar asked Oct 04 '12 22:10

Markus A.


2 Answers

How about:

class TestB extends TestA {
    Object myCopyOfFoo;

    // I assume you actually wanted this to take a parameter called foo?
    // I've left it as per the question...
    TestB() {
        this(new Object());
    }

    private TestB(Object copy) {
        super(copy);
        myCopyOfFoo = copy;
    }
}

As the second constructor is private, it can only be called within the same class (or an enclosing class) so you just need to make sure that anything calling the second constructor has made an appropriate copy, as the first constructor does.

EDIT: If your real situation is that you're taking a copy of an existing parameter, then this would work...

class ClassB extends ClassA {
    private final Foo copyOfInput;

    ClassB(Foo input) {
        super(input = input.clone());
        copyOfInput = input;
    }
}

It's pretty ugly though :(

like image 66
Jon Skeet Avatar answered Sep 21 '22 00:09

Jon Skeet


Another option:

public class TestB extends TestA {

    Object myCopyOfFoo;

    private TestB(Object foo) {
        super(foo);
        myCopyOfFoo = foo;
    }

    public static TestB createInstance() {
        Object foo = new Object();
        return new TestB(foo);
    }

}
like image 32
Ole V.V. Avatar answered Sep 20 '22 00:09

Ole V.V.