Let's talk extending classes in JavaScript.
I wrote a single page JavaScript game that I called Gibberish Cards. It's kinda like War... but dumber.
It didn't use a typical card deck, and the names of the cards were user defined. This mean I needed a list of what cards were in the game and a subset of those cards that had names. In addition I needed to know which cards a user had in his draw pile and which cards a computer had in his draw pile. I also needed to know which cards the user and computer had in their discard pile. That's 6 arrays of card objects!
So I created a Deck class.
A Simple Class
class Deck {
constructor() {
this.unplayedCards = []
}
addCardtoDeck(card) {
this.unplayedCards.push(card)
}
findCard(id) {
return this.unplayedCards.find(card => card.id === id)
}
}
I called the array of cards unplayedCards because I needed to know which cards had not already been used in the game. I had two functions in this class addCardtoDeck which was great when the game first started as I filled in all those different decks I talked about. And occasionally I need to find a card object so the findCard function was very useful.
But I also needed to keep track of what named cards existed. The computer only ever had named cards, and I didn't need to keep the named and unnamed cards separate for the user so I only needed a list of all the named cards in the game before starting.
Rather then keep track of those named cards in all Deck classes I extended the Deck class to an AllCards class.
Extending and Using super
class AllCards extends Deck {
constructor() {
super()
this.namedCards = []
}
addCardtoDeck(card) {
super.addCardtoDeck(card)
if (card.name) {
this.namedCards.push(card)
}
}
resetNamed() {
this.namedCards = this.unplayedCards.filter(card => card.name)
}
}
Because this extends from Deck I had access to the findCard and addCardtoDeck function. My constructor needed both an unplayedCards array and a namedCards array. I used the code from the Deck class by calling the super() method in the constructor.
I determined which cards were named as I filled cards into those arrays via AddCardtoDeck so I also had to extend that function. You can see in the extended function I call super.addCardtoDeck(card) to add a card to my unplayedCards array but then I have new code where I add any named cards to the namedCard array.
This would be a pointless array in the user's deck and the computer's deck so I avoided the two extra array of card objects.
I also created a function just in the AllCards class called resetNamed() which is useful after a game ends. If a user wants to play again I don't want to re-upload all the card details from the database so it recreates the namedCards array with any cards that got named during the most recent game.
There was also a lot of functions I used in the two game decks that I never needed to use for the repository of all cards so I extended another class from Deck.
Another Extended Class
class PlayableDeck extends Deck {
constructor() {
super()
this.playedCards = []
}
// here is where I placed all the functions
// only applicable to this class.
}
Similar to the AllCards* class this extends from **Deck, uses super to create a this.unplayedCards array but then also creates an array for game decks that keeps track of which cards have been played since the last reshuffle. A discard pile, if you will. I called that playedCards.
Now that I had a PlayableDeck class I was able to create a slew of functions for game play that did not need to sit in the Deck class.
- drawCard() - randomly draws an unplayed card
- moveCardToPlayed(card) - moves a card (say that card I got from drawCard()) into the playedCards array.
- removeCardFromDeck() - removes a card from played. This is used when your opponent takes your card.
- totalCards() and totalUnplayedCards() to keep track of draw and discard piles. These are also critical to know when you need to reshuffle or when you've lost the game!
- clear() - this function is clearing all cards after a game ends so you can start a new game cleanly.
3 Uniquely Similar Objects!
By extending the class I was able to have 3 Deck objects used in my code that didn't have functions or arrays baked in they would never use. It made the code cleaner and made testing easier while I coded the gameplay functionality.
Extend your classes! It's easy!
Top comments (0)