0

I have class of (sub)Objects

public class SubObjects {
    
    int depth;
    
    public SubObjects(int d) {
        this.depth = d;
    }
}

And a class of Objects

public class Objects {
    
    private int height;
    private int width;
    ArrayList<SubObjects> liste;
    
    public Objects(int h, int w) {
        this.height = h;
        this.width = w;
        this.liste = new ArrayList<>();
    }
}

The Objects hold the values height and width and an ArrayList of SubObjects. This works as intended, I do however want to store multiple types of SubObjects from different classes in these ArrayLists.

After a bit of googling I changed the Objects class to

public class Objects {
    
    private int height;
    private int width;
    ArrayList<Object> liste;
    
    public Objects(int h, int w) {
        this.height = h;
        this.width = w;
        this.liste = new ArrayList<Object>();
    }
}

This allows me, as I intended, to store Objects from a second class SubObjects2 inside the ArrayList

public class SubObjects2 {
    
    int weight;
    
    public SubObjects2(int weight) {
        this.weight = weight;
    }
}

This was great and I thought I had solved it, but then I ran the main class and while I, with the earlier implementation could return values with a getter from the objects in the ArrayList

... liste.get(i).depth (in a for loop)

The same query now returns the following error

Unresolved compilation problem: 
    depth cannot be resolved or is not a field

How do I access the values inside the SubObjects that are stored in the ArrayList now?

PeterPefi
  • 87
  • 1
  • 1
  • 7
  • Instead of `int depth` use `public int depth` – Arsh Coder Dec 19 '21 at 13:52
  • What's the difference between Objects and SubObjects? Why do they have s? Are they a collection of things? O r a single thing? Is SubObject related to Object? Maybe you mean to make SubObject extends Object? Object is made of other objects or subobjects? – Cheng Thao Dec 19 '21 at 14:11

2 Answers2

1

Your problem is that the Object class has no field with the name depth and only SubObject has this attribute

If all of your types have common attributes that you want to get it, you can create an interface and all of them should implement it it for example

interface SubObject {
    int value();
}

public class SubObjects implements SubObject {

    ...

    @Override
    public int value() {
        return depth;
    }
}

public class SubObjects2 implements SubObject {

    ...

    @Override
    public int value() {
        return weight;
    }
}
       

and now you will create a list of SubObject and in the loop, it will be

for (int i = 0; i < lists.size() ; i++) {
    int value = lists.get(i).value();
}

The other solution is to check for the type and cast it before getting the value for example

List<Object> lists = new ArrayList<>();
for (int i = 0 ; i < lists.size(); i++) {
    Object object = lists.get(i);
    if (object.getClass() == SubObjects.class) {
        SubObjects subObject = (SubObjects) object;
        int depth = subObject.depth;
    }
    
    else if if (object.getClass() == SubObjects2.class) {
        SubObjects2 subObject2 = (SubObjects2) object;
        int weight = subObject2.weight;
    }
}
AmrDeveloper
  • 3,826
  • 1
  • 21
  • 30
  • 3
    Another solution for the case where the SubObjects do not implement a common interface is to use the Visitor pattern, which is slightly more complex, but avoids the reflection required for Object.getClass(). See, for example, https://stackoverflow.com/questions/6762256/how-does-double-dispatch-work-in-visitor-pattern – GreyBeardedGeek Dec 19 '21 at 14:06
  • I assume just renaming the field in SubObjects2 to 'depth' as well won't cut it? – PeterPefi Dec 19 '21 at 14:34
  • 1
    without a common interface, you will need to check if it is SubObjects or SubObjects2 then cast it and get depth, you can name the interface method `depth` or `getDepth` and use it – AmrDeveloper Dec 19 '21 at 14:37
  • Thank you! Would you mind explaining these two lines a bit more: SubObjects subObject = (SubObjects) object; int depth = subObject.depth; – PeterPefi Dec 19 '21 at 14:50
  • 1
    The first line will cast object from `Object` type to your `SubObjects` type and now you can use it like any other SubObjects and get depth from it – AmrDeveloper Dec 19 '21 at 14:57
  • 1
    Got it, Thanks! – PeterPefi Dec 19 '21 at 15:02
0

If there's no relationships between two classes other than that they both extend Object class which all objects do and you want to store objects of those two classes in the same list, you can store them in a list of objects.

Before you can access attributes of the object, you need to cast it to the type you want to use. This is how it's done before generics.

        List list = new ArrayList(List.of(Integer.valueOf(1), "hello"));
        
        for(Object o: list){
            if (o instanceof Integer){
                System.out.println("o is an integer.");
                Integer i = (Integer) o;
                System.out.println(i.intValue());
            } else if (o instanceof String){
                System.out.println("o is a string.");
                String s = (String) o;
                System.out.println(s.length());
        }
    }
Cheng Thao
  • 1,467
  • 1
  • 3
  • 9