Hi all, I'm in the middle of building a Java Cribbage game. I've probably bit off a little more than I can chew, but if nothing else it's been a good learning experience. In addition to making a working program, one of my goals is to use good Java style. The Java courses I've taken in recent years have often discouraged the use of static variables/methods. However, I'm running into situations where I'm not sure how to avoid it. For instance, my program has about 6 classes so far, including a driver class (holds the Main method), a "Deck" class (has methods such as shuffleCards(), DealCards(), etc) and a GUI class. I have a "Deal" button in my GUI, which when clicked will call the ActionPerformed method. At this point, I would then call the dealCards() method in my Deck class, but the only way I can get this to work is if I make the Deck methods static. Then, I can just do something like this: Deck.dealCards(). How would I make this work if they were not static? Obviously I have to somehow get a Deck object into my GUI class so I can call the methods directly using the Deck instance. Just not sure how... Maybe I'm worrying about this too much? Should I just use static methods/variables for the sake of simplicity? Thanks for any help or advice!!
No, don't use static methods. There are many approaches to this, but let me just get you started in the right direction. Make the main method look more or less like this:
It might be a little longer, but not much. The CribbageGame object is responsible for creating and coordinating the elements of the game: a Deck, a Board, etc. The CribbageGUI is responsible for displaying these things, and for sending commands to them. When the CribbageGUI is constructed, it gets a CribbageGame object as a constructor argument, as shown. It stores this in a member variable. Then, when it needs to manipulate the Deck, it can say
Ernest, thanks for the reply! I *think* I'm following you.... My Main method does have a line to create the GUI object: GUI interface = new GUI(); However, what is the purpose of passing the gui object to the GUI constructor? Also, in your example, what is m_theGame? Is this just a member variable? Thanks again!
author and iconoclast
Hi Alex, I'm sorry, unfortunate typo. I make way too many typos first thing in the morning! I meant
And this implies that CribbageGUI does this in its constructor:
so that CribbageGUI always has a CribbageGame object handy. The CribbageGame, in turn, has instances of Deck, Board, etc. as members. [ October 18, 2003: Message edited by: Ernest Friedman-Hill ]
Joined: Mar 08, 2003
Thanks Ernest, I've got the idea now. I assume you would also pass the game object to all classes, not just the GUI class? So in essence, you're kind of "cross-pollinating" the objects so they can reference each other easily.... Cool. Thanks again!
author and iconoclast
What is the advantage of not using static methods in this particular example? Would you run into problems if you wanted more than one deck in a game? Would you run into problems if you wanted two games? I suspect you would run into difficulty if you wanted more than one deck because you would not be able to change the decks independantly. I suspect that having two different games would not be a problem. If you knew you were only ever going to have one deck, would having static methods be an issue?
author and iconoclast
Yes, and yes. Multiple decks and multiple games could be a problem. Whether or not multiple objects would be a problem would depend on where you kept the state. If a Deck object was immutable, meaning once it was created, its state never changed, then you'd not need more than one. But having the Game objects hold the shuffled indexes of the Deck, for example. would introduce strong coupling between the two classes, meaning that even minor changes to the Deck class would probably necessitate changes to Game, too. Having each class keep its own data is generally the best policy. Also important, further development, testing, and reuse would be harder. How would you test your Game class? One way (a currently very fashionable way, although I'm oversimplifying a bit) would basically be to create a MockDeck class which extended Deck and recorded all the method calls sent to it, hand a MockDeck object to the Game in place of a normal Deck, and then checked the logged method calls against what you expected in various curcumstances. Can't do this with static methods. Having written a proper Deck class, you could reuse it in another card game program. Perhaps you might need to change its behavior a bit: you could do this by extending Deck and overriding one or more methods -- but not if the methods were static.