It's matter of what additional public methods B will provide compared to A and how the client code will use the instance created.
If you take the List
and ArrayList
(List
is an interface but it's valid for the example), very often you will choose the class implementation for its own capabilities: ArrayList
is an auto-increasing vector that provide constant access to its elements. But the client of the class may not really care about the kind of List
implementation, and you will have more flexibility to just use this instance as a simple List
that provide the list abstraction.
Another case is about polymorphism. If you extends your example with an other class, e.g.
public class AnotherChildClass extends SuperClass {}
And you need to process a list of objects from the 2 child classes, e.g.
List<SuperClass> myList = new ArrayList<>();
myList.add(new ChildClass());
myList.add(new AnotherChildClass());
myList.add(new ChildClass());
//...
// later
(for (SuperClass s : myList) {
s.doSomeThing();
}
provided the method doSomeThing()
has been declared in SuperClass
and implemented by both children classes (or implemented in SuperClass
and possibly overridden).
Your question relates to a fundamental part of OOP which is abstraction.