1

I have an issue: There are 2 classes that implements some interfaces. In class A I have a list of objects of class B.

Is there exist a way to populate these list using class B constructor instead of hardcode every object that will be created? In class A I have method that search for particular class B object by given parameter, but the problem is to figure out how to "autopopulate" this list every time the new object is created.

I Was trying to invoke method addNodeToList() form class A, but witout an instance of this class I cant do that.

Is there any elegant way to autopopulate this list?

here is the code:

CLASS A

public class MyStructure implements IMyStructure {

  private List<INode> nodes;

  public MyStructure() {

  }

  @Override
  public INode findByCode(String code) {
    //impl
  }

  @Override
  public INode findByRenderer(String renderer) {
      //impl
  }

  @Override
  public int count() {{
    //impl  
  }

  public void addNodeToList(INode node){
      nodes.add(node);
  }
}

CLASS B

public class CompositeNode implements ICompositeNode {
private String code;
private String renderer;

MyStructure myStructure;

public static int counter;

public CompositeNode(String code, String renderer){
    this.code= code;
    this.renderer=renderer;
    myStructure.addNodeToList(this);
    counter++;
}

EDIT: I was thinking about create static list inside of class B, but I think it is not a good practice. I am out of idea how to solve this the efficent way.

FINISHED: I have created a method Inside of class A like this:

public class MyStructure implements IMyStructure {
public void addNodeToList(String code, String renderer) {

        CompositeNode node = new CompositeNode(code, renderer);

        nodes.add(node);
    }

It works the way I wanted - I dont store the list inside of class B and it populate the list it self.

MDaniluk
  • 62
  • 2
  • 2
  • 16
  • It's not at all clear what you're looking for. First, your "class A" has a `List`, but "class B" implements `ICompositeNode`, not `INode`. So unless there's something missing (maybe `ICompositeNode` extends `INode`?), you can't put "Class B" objects into the `List`. Second, your class B constructor requires two strings. If you want your class A to be able to construct class B objects without those string parameters, you will need to provide a constructor in your class B that takes no arguments. – ajb Sep 10 '17 at 21:57
  • So, how are these two classes connected to each other? – Mick Mnemonic Sep 10 '17 at 21:58
  • Responding to your edit: if it's efficiency you're after, I don't think there's a way to gain too much. If you want a list with 10 items of class B, you'll have to call a class B constructor 10 times. I don't think there's a magic way in Java to allocate space for 10 objects all at once and initialize them. You could perhaps devise something like this in C++. Is that what you were trying to achieve? – ajb Sep 10 '17 at 22:02
  • @ajb ICompositeNode extends INode. I don;t mention that. Sorry I dont want to my class A create objects of class B without these parameters. but I think that could work, I can delegate a method that will construct object of class B inside of class A (With required parametrs.) public void makeAnObject(String code, String renderer){ //imp } Thanks I think You helped me a lot! I need to try this in code. ;) – MDaniluk Sep 10 '17 at 22:03
  • What is your current auto populate strategy? Or if there not then can you please tell what will be the source of auto populate data? – muasif80 Sep 10 '17 at 22:04
  • @MickMnemonic the connection between these classes is that class A implements method to look after objects of INode, class B implements this interface (ICompositeNode extends INode) – MDaniluk Sep 10 '17 at 22:08

2 Answers2

0

Without knowing further context and usage I would simply add a getter in class A:

public class MyStructure implements IMyStructure {
    //...
    public List<INode> getNodes() {
        return this.nodes;
    }
   //..
}

and then it can be used in class B to add an element to the list of class A:

public CompositeNode(String code, String renderer){
    //...
    myStructure.getNodes.add(this);
    //...
}

I don't think you need the addNodeToList method, unless used elsewhere.

Grzegorz Górkiewicz
  • 4,496
  • 4
  • 22
  • 38
  • 1
    I made something similar, make a method inside class A where I passed the creating class B objects. of course with required parametrs. but Your Idea is intersting. thanks for help, Grzesiu ;) greetings from Poland :) – MDaniluk Sep 10 '17 at 22:30
  • There's quite a few bad practices here. Answer is still correct, just bad design. `myStructure.getNodes.add(this)` violates [LoD](https://en.wikipedia.org/wiki/Law_of_Demeter) and [leaks the object via constructor](https://stackoverflow.com/questions/3921616/leaking-this-in-constructor-warning). [Content coupling](https://en.wikipedia.org/wiki/Coupling_(computer_programming)#Types_of_coupling) usually leads to code that's difficult to scale and debug. The `addToNode` would actually avoid violating LoD (not to mention, give room for impl changes if needed). Just some things to look into – Vince Sep 10 '17 at 23:08
0

You can instantiate the list of INode objects and add the first node in the MyStructure's constructor so you can create CompositeNode with MyStructure object filled with CompositeNode object in this way:

MyStructure

public class MyStructure implements IMyStructure {
    private List<INode> nodes;

    public MyStructure() {
        super();
    }

    public MyStructure(INode node) {
        nodes = new ArrayList<>();
        nodes.add(node);
    }
    //...
}

CompositeNode

public class CompositeNode implements ICompositeNode {
    private String code;
    private String renderer;
    private MyStructure myStructure;

    public static int counter;

    public CompositeNode(String code, String renderer){
        this.code= code;
        this.renderer=renderer;
        myStructure = new MyStructure(this);
        counter++;
    }
    //...
}
  • I think that is very bad idea. doing I will always have only 1 INode in the list, because every tme I will execute CompositeNode costructor compiler will execute statement: `new MyStructure() `-> and because of this `new ArrayList` is created (code in MyStructure constructor) – MDaniluk Sep 10 '17 at 22:55
  • When you create a CompositeNode object, the costructor create MyStructure instance and list inside it with the first node. If you want to add other elements to the list you can get list element and add it. – user8589247 Sep 10 '17 at 23:04
  • sorry I didnt replied earlier but I had some unexpected duties to manage. regarding to the post. I think your logic is incorrect inside of `MyStructure` constructor you have: `new ArrayList<>();` statement, so every time you execute `CompositeNode` constructor you are creating `MyStructure` objects, and each `MyStructure` object contain `new ArrayList`. this mean that every list contain only 1 INode element. and this wasn't the case. – MDaniluk Sep 14 '17 at 11:26