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.

sciamp-dev
  • 11
  • 5
  • 4
    Possible duplicate of [Is it a code smell to store generic objects in a container and then get object and downcast the objects from container?](https://softwareengineering.stackexchange.com/questions/321805/is-it-a-code-smell-to-store-generic-objects-in-a-container-and-then-get-object-a) – Doc Brown May 17 '17 at 21:19
  • 3
    ... or in other words: implement your code which deals with `List` 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 01:37
  • @DocBrown That's the problem, because I want a Class to be a container of other classes having some common attributes. The key point is "some attributes" not "every attribute" and I don't want to to have virtual methods in the Parent Class that are empty in some of the Childs. It seems wrong to me. So yeah, it's a design problem, but I can still change it – sciamp-dev May 18 '17 at 10:19
  • @BenCottrell I'm using the MVC pattern to design the application and this class is into the Model, so yes, they are for the most simple POJO classes with only getter and setters. Even if there are other little methods I can move them into a Class in a higher level of abstraction of the Controller – sciamp-dev May 18 '17 at 10:23
  • 1
    @Champ: for "common attributes" you will probably be better off by [favoring composition over inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance). However, you need to analyse why you think you need one `List` instead of two lists `List` and `List`. 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
  • @DocBrown thanks for the answer. I edited the question adding an example an describing what I'd like to achieve – sciamp-dev May 18 '17 at 16:46

1 Answers1

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.

Doc Brown
  • 199,015
  • 33
  • 367
  • 565