Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Interfaces and polymorphism design questions - I would appreciate some input

 
Roland Wynn
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So, I am designing this game. Before you say anything, yes I know there is a game development board, but this really isn't a question about the actual design, just the programming aspect of it. But, if you must move it, then do what you have to do.

Anyway, it's a card game for two players. The cards used are not of the standard 52-deck variety. Instead these cards perform various different actions. On the inside plumbing, these actions simply increase or decrease values and set flags. Now, I originally had each item as a enum type that was populated into a LIFO stack, and had the program run through a two-step switch block. I've found that's it's, more than likely, easier to use an interface for the cards, and have each different type of card in it's own class with implementation of that interface.

By creating a class, like PlayCard for example, I can accept an argument of type interface and define a new method that calls the action method of the argument passed... Right? That's what I was understanding in the book I was reading.

Then, I can define another method inside the Player class (which defines the characteristics of the human player - you), and call that intermediate PlayCard class, passing an argument of object card.

So, an interface like...

And, then, I could construct a card class...

Something to play the card...

And, finally, I can simply make the object and call the method:


So, I just pass along the argument of the card object and polymorphism does its thing and calls it's own doAction() method. Right? It all seems necessary to gain polymorphic behavior, but is that 'intermediate' class (the PlayCard) one, required?

There's also something else... When a card is played, I only want that action to occur to that specific player. In other words, I don't want to have to pass another argument, like a string value, declaring the origin, and then having it checked to see which person the program should assign values to. What's the best way to handle this? Another interface? I guess that's the part I'm confused on. If the players share a common interface, I could make another 'middle' method that alters a value, but I wanted those values separate and private, with their own acessor and mutator methods. But, I guess I could get rid of those and make them static inside main().

I kinda just need some insight and see if I'm doing something wrong, or if I am understanding my book's principles incorrectly. Or, maybe, just a push in the right direction.

Also, if anyone can answer this.. Is it possible to create a stack of an interface type? Using the above example: Stack<CardBase> deck = new Stack<CardBase>(); If so, how would you instantiate a new object and put it right onto the stack in the same statement? Or, would I need two?
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24208
35
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

All good questions -- these are great things to be thinking about!

Short answers to well-asked questions:

First, the PlayCard class is wholly unnecessary. Players can call doAction() on individual cards. If you have Stack<CardBase>, and you're just calling doAction() on each card, then that's polymorphic behavior right there.

Second, yes, the card probably needs to know about the player so it can set the flags and things in the player object. So just give doAction() an argument of type Player



and let Players call it like this:



and then classes like CardA can do



And third, yes, you can create a stack of interface type, and no, you can't push a card onto it in the same statement. Use two lines of code.
 
Campbell Ritchie
Sheriff
Posts: 48415
56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And welcome to JavaRanch
 
Brian Legg
Ranch Hand
Posts: 488
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I did the same type of thing with my game. Just replace your cards with enemies.

I set up a generic interface called Enemy. Each specific enemy implemented the Enemy interface and added it's own specific code like speed, direction, health, etc. Then I keep them all in a collection, loop through them, and call the action() method on each one of them without needing to know what type of enemy it is... just that it is some kind of Enemy. That's the beauty of polymorphism. I also set up a Collectable interface for objects which were able to be collected. If you couldn't guess yet it was a platformer ;)

I think Ernest answered all the good ones

j/k
 
Roland Wynn
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ernest Friedman-Hill wrote:
First, the PlayCard class is wholly unnecessary. Players can call doAction() on individual cards. If you have Stack<CardBase>, and you're just calling doAction() on each card, then that's polymorphic behavior right there.

Ah, that's right! I forgot about that. Actually, they'll be popped into a hand, but I can still call the method based on the position of that array or vector. It makes sense when you think about it. Hmmm starting to all make sense, now.
Campbell Ritchie wrote:
And welcome to JavaRanch

Thanks!

Brian Legg: Hmm, interesting. This game isn't as action-based as that, but something to think about. I have to admit, OOP programming practices can be frustrating sometimes when you can't fully understand it. But, when it all locks into place, it's something quite magical.

Thank you all for your suggestions and comments.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic