views:

145

answers:

6

I have a lot of objects of type ContainedClass stored in an object of type ContainingClass. I need to access the container object from the inside objects. As of now I am doing this by passing a reference to the container object in the constructor of the other objects like ContainedClass cclass = new ContainedClass(this); and storing it as ContainingClass owner.

This seems ugly to me, and the solution that seems fitting to me is using inner classes, but the definition for ContainedClass is very large and that seems to be inappropriate. So which of the options should I go with? Or is there another obvious option I'm missing?

Here is a piece of sample code I found online depicting what I'd be going for using inner classes.

public class TestIt {
  public static void main(String a[]){
     new TestIt().doit();
     /*
      output :
      Hello world!
     */ 
  }
  public void doit() {
      new InnerClass().sayHello();
  }
  public void enclosingClassMethod(){
      System.out.println("Hello world!");
  }


 class InnerClass {
   public void sayHello() {
     TestIt.this.enclosingClassMethod();
   }
 }
}

I should add that the other benefit of inner classes I was looking at was that ContainedClass could only exist in ContainerClass, which is a desired outcome.

+2  A: 

What you've done with your ContainedClass cclass = new ContainedClass(this); construct is replicate exactly what inner classes do under the covers. There may be reasons to not use inner classes, but size of the class isn't really one of them. I'd use the real language feature rather than emulating it unless there was a good reason not to use the real deal.

Laurence Gonsalves
A: 

If I were you, I would stick with what you were doing before rather than switching to inner classes. Their syntax is unweildy at times (especially since this is not a static inner class, but a per-instance class), and you are just going to be stuffing lots of code in one file.

The parent/child relationship you were using before is not all that uncommon, and I don't find it that ugly, personally.

Tim Yates
+1  A: 

I would use a factoryMethod in this case :

class ContainingClass {
...
    ContainedClass createContainedObject() {
        return new ContainedClass(this);
    }
...
}

in the code it would look like

jar = new ContainingClass();
bean = jar.createContainingClass();

It is a bit side stepping the issue, but I find it expressive and allows me to choose whether or not to use an inner class. I personally do not like large inner classes, I find them difficult to read.

Peter Tillemans
+2  A: 

I think it depends on how highly-coupled the parent/child classes are. If the child needs access to many member variables that you wouldn't otherwise expose via getters/setters, or many member functions that would otherwise be private, then the inner class arrangement will be cleaner.

But if the child class will be using the existing public interface of the parent, then I think it is cleaner to separate them. Adding just one additional parameter to the constructor isn't bad. You can even introduce an interface to describe which parts of the parent are accessed from the child. This makes it easy to unit test the child class separate from the parent class (using mock objects, for instance).

Harold L
The main reason I liked the idea of using an inner class was the fact that I could combine everything into a single class. That way I wouldn't have public functions and an external class available when the only need for those functions and classes were in relation to one another.
Kyle
A: 

Large classes of any flavour should generally be frowned upon as they tend to have multiple responsibilities and are a pain to isolate and test.

Your solution will ultimately depend on why the ContainedClass needs to know about the ContainerClass. If the intent is to share common data / initialisation code between ContainedClasses then the Factory approach might yield good results. Or perhaps if you just want to keep track of your ContainedClasses then you might want to consider an Event / EventListener model.

CurtainDog
A: 
  1. Inner class should be used for creating throwaway objects.
  2. if only the top level class uses this class , then go for inner class.
  3. Please read Effective Java by Joshua Bloch ,to get clear idea.
Suresh S