Moun Glow Moun Glow - 13 days ago 7
Java Question

can't use parent method with child without ovrriding?

i have this code :



public class Cardmo {
public static void main(String[] args){
Decke poker = new Decke();

poker.shuffle();

PokerHand h1 = poker.deal();

// problem : it prints a hole new deck and not the PokerHand h1 ??
h1.print();
}
}

class Carte{
int suit, rank;

static String[] suits = { "Clubs", "Diamonds", "Hearts", "Spades" };
static String[] ranks = { "narf", "Ace", "2", "3", "4", "5", "6",
"7", "8", "9", "10", "Jack", "Queen", "King" };

public Carte(){
this.suit = 0;
this.rank = 0;
}

public Carte(int suit, int rank){
this.suit = suit;
this.rank = rank;
}

public void print(){
System.out.println(ranks[rank] + " of " + suits[suit]);
}

public String toString(){
return ranks[rank] + " of " + suits[suit];
}
}
class Decke{
Carte[] cartes;

public Decke(int n) {
this.cartes = new Carte[n];
}

public Decke() {
this.cartes = new Carte[52];

int index = 0;
for (int suit = 0; suit <= 3; suit++) {
for (int rank = 1; rank <= 13; rank++) {
this.cartes[index] = new Carte(suit, rank);
index++;
}
}
}

public void print(){
for(int i = 0; i < cartes.length; i++){
cartes[i].print();
}
}

public int randomInt(int low, int high){
int x = (int)(Math.random() * (high-low) + low);
return x;
}

public void swapCartes(int i, int j){
Carte t = cartes[i];
cartes[i] = cartes[j];
cartes[j] = t;
}
public void shuffle(){
for(int i =0; i < cartes.length; i ++){
int swap = randomInt(i, cartes.length);
swapCartes(i, swap);
}
}

public Decke subDecke(int low, int high){
Decke sub = new Decke(high - low + 1);

for(int i = 0; i < sub.cartes.length; i++){
sub.cartes[i] = this.cartes[low + i];
}

return sub;
}

public PokerHand deal(int low){
Decke hand = this.subDecke(low, low + 4);
PokerHand pokerhand = new PokerHand();

for(int i = 0; i < hand.cartes.length; i++){
pokerhand.hand[i] = hand.cartes[i];
}

return pokerhand;
}
}

class PokerHand extends Decke{
Carte[] hand = new Carte[5];

public PokerHand(){}

//why override?? why not use the parent one ??
/* public void print(){
for(int i = 0; i < 5; i++){
hand[i].print();
}
}*/
}





as you can see my problem is whenever i try to use the print() method from the parent it prints a hole new deck and not the hand h1 ?? also whenever i try to shuffle h1 using the parent method h1.shuffle(); it doesn't work why?? i mean how do i use the parent methods correctly??

I know its a real basic question but yea anyways thanks in advance!

Answer

The solution is simple: PokerHand should not extend Decke. These two logical entities do not satisfy the "is-a" relationship (nor the "has-a" relationship for that matter) as they both will have drastically different behaviors. Make PokerHand its own class, one that has Cards, and again one that does not extend Decke. If you want both classes to share methods, then they may need a common abstract parent class (I doubt) or an interface (perhaps).

I would also use enums for Suits and Ranks, and rather than a print method, override each key class's toString() method. This way it will work as is within a println statement.

Also, I would use enums (a newer type of Java constants) for your Rank and Suit. These are the canonical use case for use of enums. Something like:

enum Suit {
    CLUBS("Clubs"), DIAMONDS("Diamonds"), HEARTS("Hearts"), SPADES("Spades");
    private String name;

    private Suit(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return getName();
    }
}

enum Rank {
    ACE("Ace"), TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), SIX("6"), SEVEN("7"), EIGHT("8"), 
    NINE("9"), TEN("10"), JACK("Jack"), QUEEN("Queen"), KING("King");

    private String name;

    private Rank(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return getName();
    }
}

And then Card would use the above in a "has-a" relationship:

class Card {
    private final Suit suit;
    private final Rank rank;
    public Card(Suit suit, Rank rank) {
        this.suit = suit;
        this.rank = rank;
    }

    public Suit getSuit() {
        return suit;
    }

    public Rank getRank() {
        return rank;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((rank == null) ? 0 : rank.hashCode());
        result = prime * result + ((suit == null) ? 0 : suit.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Card other = (Card) obj;
        if (rank != other.rank)
            return false;
        if (suit != other.suit)
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Card [suit=" + suit + ", rank=" + rank + "]";
    }

}

You might want to give Card an equals and hashCode method so that you can tell if two Cards are functionally equal.

Then Deck and Hand can actually share a super class, say called CardCollection as on deeper thought, I do see that they share behaviors:

// super class for both Deck and Hand
abstract class CardCollection implements Iterable<Card> {
    private List<Card> cards = new ArrayList<>();

    public void addCard(Card card) {
        cards.add(card);
    }

    public Card discardCard() {
        // TODO: throw an exception if size is 0
        return cards.remove(0);
    }

    public List<Card> getCards() {
        return cards;
    }

    public int size() {
        return cards.size();
    }

    @Override
    public Iterator<Card> iterator() {
        return cards.iterator();
    }

    @Override
    public String toString() {
        return "CardCollection [cards=" + cards + "]";
    }

    public void clear() {
        cards.clear();
    }

}

class Deck extends CardCollection {
    public Deck() {
        renew();
    }

    public void renew() {
        clear();
        for (Suit suit : Suit.values()) {
            for (Rank rank : Rank.values()) {
                addCard(new Card(suit, rank));
            }
        }
        Collections.shuffle(getCards());
    }

    public Card deal() {
        return discardCard();
    }

}

class Hand extends CardCollection {

    public static final int HAND_SIZE = 5;

}
Comments