Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a new object class or write a method which converts sub-class objects? or something else? Performance NOT Preference

I've put together two separate programs which play a card game called 'Crazy Eights'.

The classes I've written for this program are based on a default 'card' package which provides playing card objects and some generic methods for playing cards.

I've taken two separate approaches to achieve this which are both functional in their own right.

Here are two UML class diagrams which depict the two approaches:

Inherited subclass 'conversion' method

enter image description here

Composed subclass with similar methods

enter image description here

As you can see in approach 1 the class EightsCard contains a method convert(Card) Here's the method:

  /**
   * Converts a Card into an EightsCard
   * @param card The card to be converted
   * @return The converted EightsCard
   */
   public EightsCard convert(Card card) {
     if (card != null) {
     EightsCard result = new EightsCard(card.getRank(), card.getSuit());
     return result;
     } 
     return null;
   }
 }

This method allows you to call methods from CardCollection which otherwise wouldn't be legal. For example, in the play method from the EightsPlayer class shown below:

  /**
   * Removes and returns a legal card from the player's hand.
   */
  public EightsCard play(Eights eights, EightsCard prev) {
    EightsCard ecard = new EightsCard(0, 0);
    ecard = ecard.convert(searchForMatch(prev));
    if (ecard == null) {
      ecard = drawForMatch(eights, prev);
      return ecard;
    }
    return ecard;
  }

Approach 2 doesn't require any conversions as the similar methods have been written in a new class EightsCardCollection which extends CardCollection. Now the play methods can be written like this:

  public EightsCard play(Eights eights, EightsCard prev) {
    EightsCard card = searchForMatch(prev);
    if (card == null) {
      card = drawForMatch(eights, prev);
    }
    return card;
  }

This brings me to a couple of questions:

  • Are there any advantages to either approach beyond personal preference?
  • Is there a better way to compose this program?

For example, might it be better to write 'similar' classes which are more specific1 and not use default classes2 at all.

1 labelled 'crazyeights.syd.jjj' or 'chaptwelvetofort' in the class diagrams.

2 labelled 'defaults.syd.jjj' or cards.syd.jjj' in the class diagrams.

like image 720
Josh Hardman Avatar asked May 22 '18 05:05

Josh Hardman


People also ask

Can an object be a subclass of another object?

Can an object be a subclass of another object? A. Yes—as long as single inheritance is followed.


1 Answers

Too many subclasses

Neither of these approaches is very good, as both of them have more subclasses than necessary. Why does EightsCard extend Card? What if you wanted to implement some other card game? (There are quite a few, you know...) Would you make one subclass for each card game? Please don't.

I would have these classes:

  • Card
  • CardCollection
  • Player

I wouldn't even have a Deck class as it seems like it does nothing else than extend CardCollection without providing any more functionality.

Then I would have one class for each game implementation, so one EightsController class that handles the game logic for that game. No specific class for EightsCard, no specific class for EightsCardCollection, etc.

The reason is simple: You don't need anything more than this. A Card and a CardCollection is exactly the same no matter which card game you are playing. A Player is also the same thing in all games.

like image 83
Simon Forsberg Avatar answered Sep 21 '22 05:09

Simon Forsberg