Java - 非泛型类扩展泛型类

时间:2015-03-27 22:13:47

标签: java class generics inheritance

我想知道如何(如果可能的话)我可以创建一个类,这是一个特定类型的泛型类。

具体来说,我有一个abstract class Stack<Type>已经实现了所有必要的方法,我希望有一个class StackInteger,而StackInteger的实例也是Stack<Integer>的一个实例}。

我知道我可以这样做:

class StackInteger {
    Stack<Integer> s;

    public StackInteger(int size) {
        s = new Stack<Integer>(size);
    }

}

然后实现所有 Stack 方法以包含s.method();,但我想知道从 Stack 扩展时我是否可以轻松完成。

3 个答案:

答案 0 :(得分:3)

是的,在这种情况下,继承是比合成更好的解决方案,因为StackIntegerStack

只需在Integer子句中提供extends作为类型参数。

class StackInteger extends Stack<Integer>

但是,如果您没有提供超出Stack已有的任何其他功能,那么此类无用,您也可以使用Stack<Integer>

答案 1 :(得分:2)

我建议不要扩展泛型类以克服泛型冗长。这是一个反模式,称为pseudo-typedef antipattern

来自文章:

  

如果方法参数的类型为StringList,则无法将普通List传递给它。这意味着你根本不能使用假型作为方法参数,而不要求每次使用该方法都使用假型,实际上这意味着你不能在库API中使用假型。

...

  

伪类型反模式的另一个问题是它倾向于忽略使用接口来定义变量类型和方法参数的好处。虽然可以将StringList定义为扩展List的接口和扩展ArrayList并实现StringList的具体类型StringArrayList,但伪typedef反模式的大多数用户通常不会达到此长度,因为此技术的目的主要是简化和缩短类型名称。因此,API将不那么有用且更脆弱,因为它们使用像ArrayList这样的具体类型而不是像List这样的抽象类型。

那么,为什么不坚持Stack<Integer>?我不认为它太糟糕了。

答案 2 :(得分:1)

是的,你可以做到。

class StackInteger extends Stack<Integer> {
    ....
}

正如@Magnamag所指出的,这通常被认为是反模式。如果只是为了避免必须指定类型参数,则尤其如此。

然而,可以有合法的方法来做到这一点。例如,如果非泛型类是private,则该类的用户无论如何都将被强制编程到接口(或抽象类)。在这个例子中(公认的是相当人为),有一个静态方法返回一个扩展AbstractList<String>的非通用匿名类。

public class Main  {

    public static List<String> helloWorld() {
        return new AbstractList<String>() {
            @Override
            public String get(int i) {
                switch (i) {
                    case 0: return "Hello";
                    case 1: return "World";
                    default: throw new ArrayIndexOutOfBoundsException();
                }
            }
            @Override
            public int size() {
                return 2;
            }
        };
    }

    public static void main(String[] args) {
        System.out.println(helloWorld());
    } 
}