0

I am working on the design problem, where I have to design a deck of cards. Here is how my classes look like

public interface ISuit {
    String getLogo();
    String getName();
}

public interface Icard<T extends ISuit> {
    T getSuit();
    String getNumber();
}

Now, I want to write a class for each of the 13 cards, something along the lines of this

public  class Queen<E extends ISuit> implements Icard<E> {
    @Override
    public String getNumber() {
        return "12";
    }

    @Override
    public E getSuit() {
        return new E;
    }

}

I intend to create object of Queen like this
1: Queen<Hearts> queenOfhearts = new Queen<Hearts>();

However, for my queen class, I have a compile time error for getSuit. I don't know what is supposed to be the definition of getSuit. Is this function supposed to be made abstract?

Max
  • 9,100
  • 25
  • 72
  • 109
  • 1
    Is `Hearts` really its own class in your design? Especially for ranks and suits, using enums might make more sense. – Silly Freak Sep 21 '14 at 08:19
  • @SillyFreak I want to be able to add new suits in future. Also I am learning the OOP concepts. – Max Sep 21 '14 at 08:20
  • Think about it this way: Do you need type safety of `King` vs `Queen`, like you'd want it for `Bike` vs `Car`, or do you just need objects with the right attributes? If it's the second, then a `Card` class (if you don't want an `enum`) with two constructor parameters might make more sense. In regard to adding suits in the future, no matter whether you use an enum or an own class for each suit, you'll need to recompile your code for adding the new suit. Making each suit only an object lets you add suits at runtime/without recompiling. – Silly Freak Sep 21 '14 at 08:34

3 Answers3

1

At runtime, if you want to instantiate a generic type T, you have to have the Class<T> object.

You can change the signature of the getSuit(..) method to:

public E getSuit(Class<E> clazz);

Then, the implementation would be:

public E getSuit(Class<E> clazz) {
    try {
        return clazz.newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
    // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
}

Even better, in order to get rid of the Class<T> parameter of the method, you can pass it to the class's constructor and persist it to a private member. For example:

public  class Queen<E extends ISuit> implements Icard<E> {
    private Class<E> clazz;

    public Queen(Class<E> clazz) {
        this.clazz = clazz;
    }

    public String getNumber() {
        return "12";
    }

    public E getSuit() {
        try {
            return clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}
Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
0

Make Queen an abstract class that implements getNumber(). Implement getSuit() in derived classes like QueenHearts.

J0e3gan
  • 8,740
  • 10
  • 53
  • 80
Tomek
  • 543
  • 4
  • 12
0

First off, I believe that your idea of how to go about the problem is incorrect from an object oriented approach. You want to have Card be a class with two instance variables: number and suit.

Then, in order to have each of the 13 cards, you create 13 objects and give them the correct card number/suit. For instance,

Suit hearts = new Suit("Hearts");
Card queenHearts = new Card(12,hearts);

As to the actual reason behind your compile time error, take a look at Instantiating object of type parameter .

Community
  • 1
  • 1
NoseKnowsAll
  • 4,593
  • 2
  • 23
  • 44