2014-09-21 57 views
0

我正在设计问题,我必须设计一副牌。这里是我的课怎么看起来像解释后面的编译时错误wrt java泛型?

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

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

现在,我想写一类为每个13张牌,沿着这

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

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

} 

线的东西我打算创建女王的对象像这
1:Queen<Hearts> queenOfhearts = new Queen<Hearts>();

但是,对于我的皇后班,我有一个getSuit编译时错误。我不知道什么应该是getSuit的定义。这个功能应该是抽象的吗?

+1

在设计中'Hearts'真的是它自己的类吗?特别是对于排名和套装,使用枚举可能更有意义。 – 2014-09-21 08:19:11

+0

@SillyFreak我希望能够在将来添加新的西装。另外我正在学习面向对象的概念。 – Dude 2014-09-21 08:20:32

+0

这样想:你需要'King'和'Queen'的类型安全吗?就像你想要'Bike' vs'Car',或者你需要具有正确属性的对象?如果是第二个,则使用两个构造函数参数的'Card'类(如果您不想使用'enum')可能更有意义。 关于未来添加套装,无论您是否为每套套装使用枚举或自己的类,您都需要重新编译代码以添加新套装。使每个诉讼只有一个对象可以让你在运行时添加诉讼/不需要重新编译。 – 2014-09-21 08:34:33

回答

1

在运行时,如果要实例化一个通用类型T,则必须具有Class<T>对象。

您可以更改getSuit(..)方法来签名:

public E getSuit(Class<E> clazz); 

然后,实现将是:

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

更妙的是,为了摆脱对Class<T>参数方法,你可以将它传递给类的构造函数并将其保存到私有成员中。例如:

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; 
    } 
} 
+0

不是非常直观或方便。如果你要使用类型参数,那么最好使它们成为构造函数的参数 – radai 2014-09-21 08:21:08

+0

当然,这只是一个提示。他应该改进设计。 – 2014-09-21 08:21:57

0

使Queen抽象类实现getNumber()。在派生类中执行getSuit(),如QueenHearts

0

首先,我相信你的如何去这个问题的想法是不正确从面向对象的方法。你想让Card成为一个具有两个实例变量的类:数字和套装。

然后,为了拥有13张卡片中的每张卡片,您可以创建13个对象并为其提供正确的卡号/套装。例如,

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

至于编译时错误背后的实际原因,请看Instantiating object of type parameter