javainheritancejavafxpolymorphismobservablelist

JavaFX ObservableList<SuperClass> does not keep SubClass attributes


I have an ObservableList<superclass> that holds subclass objects. When I try to access attributes specific to the subclass, they seem to be missing despite being passed to the superclass list.

public abstract class SuperClass {
     private int superAttribute;
}
public class SubClassA extends SuperClass {
     private int subAttributeA;
}
public class SubClassB extends SuperClass {
     private int subAttributeB;
}
public class ListClass {
     private static ObservableList<SuperClass> list = FXCollections.observableArrayList();
}

In another class I create an instance of a subclass object and add it to list

public class SomeClass {
     SubClassA subObject = new SubClassA(superAttribute, subAttributeA);
     ListClass.addToList(subObject);
}

When I try to access subAttributeA it is returned as a default value. e.g I create the object with subAttributeA as 1234 and when I try to access it, it is 0. System.Out.Println(ListClass.list.getFirst().getSubAttributeA()) returns nothing useful.

A few things to note. This is for an assignment, so I do not have leeway on how the classes are structured. There can only be one list holding both subclasses.

I have tried to cast the object to its subtype in the addToList method

public static void addToList(SuperClass objectToBeAdded) {
if (objectToBeAdded instanceof SubClassA) {
           ((SubClassA)list.getLast().setSubAttributeA(((SubClassA) objectToBeAdded).getSubAttributeA()); 

Solution

  • ObservableLists can manage references to polymorphic objects with no problem.

    Probably there is some error in the code you don't show. You may have some misconception on your understanding of polymorphism and use of it in Java (I can't say).

    Here is a working example, perhaps you can study it and compare it to your broken code.

    The output is:

    List content:
    [SubClassA{subAttributeA=11} SuperClass{superAttribute=1}, SubClassB{subAttributeB=22} SuperClass{superAttribute=2}]
    First element, sub attribute A:
    11
    

    The code that generates it is:

    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    
    public class SuperTester {
        public static void main(String[] args) {
            ListClass.addToList(new SubClassA(11, 1));
            ListClass.addToList(new SubClassB(22, 2));
    
            System.out.println(
                    "List content:\n" +
                    ListClass.getList()
            );
    
            System.out.println(
                    "First element, sub attribute A:\n" +
                    ((SubClassA) ListClass.getList().getFirst()).getSubAttributeA()
            );
        }
    }
    
    abstract class SuperClass {
        private int superAttribute;
    
        SuperClass(int superAttribute) {
            this.superAttribute = superAttribute;
        }
    
        public int getSuperAttribute() {
            return superAttribute;
        }
    
        @Override
        public String toString() {
            return "SuperClass{" +
                    "superAttribute=" + superAttribute +
                    '}';
        }
    }
    
    class SubClassA extends SuperClass {
        private int subAttributeA;
    
        SubClassA(int subAttributeA, int superAttribute) {
            super(superAttribute);
            this.subAttributeA = subAttributeA;
        }
    
        public int getSubAttributeA() {
            return subAttributeA;
        }
    
        @Override
        public String toString() {
            return "SubClassA{" +
                    "subAttributeA=" + subAttributeA +
                    "} " + super.toString();
        }
    }
    
    class SubClassB extends SuperClass {
        private int subAttributeB;
    
        SubClassB(int subAttributeB, int superAttribute) {
            super(superAttribute);
            this.subAttributeB = subAttributeB;
        }
    
        public int getSubAttributeB() {
            return subAttributeB;
        }
    
        @Override
        public String toString() {
            return "SubClassB{" +
                    "subAttributeB=" + subAttributeB +
                    "} " + super.toString();
        }
    }
    
    class ListClass {
        private static ObservableList<SuperClass> list = FXCollections.observableArrayList();
    
        public static void addToList(SuperClass objectToBeAdded) {
            list.add(objectToBeAdded);
        }
    
        public static ObservableList<SuperClass> getList() {
            return list;
        }
    }
    

    Static storage like the ListClass you have in your question is usually a bad idea, but that's incidental info and isn't really relevant to your question.