0

I'm working on a project for my College and I'm stuck on this problem in my design. Right now I have something like:

public abstract class AbstractClass {
    protected SomeClass attributeOne;
    protected SomeClass2 attributeTwo;

    public SomeClass getAttributeOne() { // code }
    public SomeClass2 getAttributeTwo() { // code }

    public void setAttributeOne(...) { // code }
    public void setAttributeTwo(...) { // code }
}

public class ChildClassOne extends AbstractClass {
    private SomeOtherClass childOneAttributeOne;

    public SomeOtherClass getChildOneAttributeOne() { // code }

    public void setChildOneAttributeOne(...) { // code }
}

public class ChildClassTwo extends AbstractClass {
    private SomeOtherClass childTwoAttributeOne;
    private SomeOtherClass2 childTwoAttributeTwo;

    public SomeOtherClass getChildTwoAttributeOne() { // code }
    public SomeOtherClass2 getChildTwoAttributeTwo() { // code }

    public void setChildTwoAttributeOne(...) { // code }
    public void setChildTwoAttributeTwo(...) { // code }
}

In another class in a higher level of abstraction, I have a Class with a

private List<AbstractClass> = new ArrayList<>();

And then when needed I add different instances of ChildClassOne and ChildClassTwo. However I need to get access to the different methods in every subclass in certain cases, but I may not know what kind of Child they are (so I can't always do a cast) and I don't want to do a switch of InstanceOf. It just feels bad. Another problem is that I have lots of subclasses, so I can't really declare an attribute for every single of them.

As possible solutions, I've seen the Adapter and the Composite pattern, but I really don't know if they are the correct approach, if there's a better solution or if my design is totally wrong.

EDIT: Yes I must use Java for this project

EDIT2: Actuale use case

Link to a simplified example:

I have a group of different cards, with some basic attributes. And I have two Classes containing a List of Card (in the example is only one (CardContainer) for sake of simplicity). Card is the abstract class and CardWithAction and CardWithBonus are my childs (they are actually 4 at the moment). In one of the "container" Class I only need access to the methods of the parent class (Card), so there's no problem right now. But in the other "container" I may need access to the methods of the childs, considering that most of the time I would like to treat them like a single object.

  • 4
  • 3
    ... or in other words: implement your code which deals with List<AbstractClass> in a fashion it uses only virtual methods of the base class, which are (or might be) overriden in the derived classes. If you have problems to do this, it is likely you have a design problem somewhere in your inheritance hierarchy. – Doc Brown May 17 '17 at 21:25
  • Do your classes have any actual behaviour (i.e. methods which actually "do stuff" and contain real application logic)? Are they simple POJO classes which only contain getters and setters? Remember that POJO classes with no behaviour do not really represent 'objects' in the true OO sense, they're really just data entities. Don't feel obliged to apply OO concepts to data entities; in particular, Inheritance relationships frequently don't actually provide any tangible benefits for POJOs – Ben Cottrell May 17 '17 at 22:13
  • Do you have to use Java for this project? In general, Java does not have the capability to express this pattern (what you want is discriminated unions) – gardenhead May 18 '17 at 1:37
  • 1
    @Champ: for "common attributes" you will probably be better off by favoring composition over inheritance. However, you need to analyse why you think you need one List<AbstractClass> instead of two lists List<ChildClassOne> and List<ChildClassTwo>. If there is a use case which is going to deal with objects of type ChildClassOne and ChildClassTwo in a uniform manner, "virtual functions" are the right tool. If you need help for this, you need to describe that actual use case in detail in your question. – Doc Brown May 18 '17 at 11:53
0

I suggest you keep things simple and use composition instead of inheritance, as I wrote in a comment. Instead of having classes CardWithAction and CardWithBonus, create a class Action and a class Bonus, and make your Card optionally containing a reference to a Bonus object and an optional reference to an Action object.

When iterating over a container of cards, you can just check for actions like

  if(card.getAction()!=null)
  {
       // do something with card.getAction().getReward();
  }

That will avoid the need for casts or "InstanceOf". As a "bonus" (pun intended), you can now have card with an action and a bonus, in case you need that.

  • Thanks for the answer! In the end I decided to use composition with Interfaces to solve the problem – sciamp-dev May 19 '17 at 18:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.