简体   繁体   English

Java 泛型类型扩展多个类

[英]Java Generic Type extend multiple classes

How can the type for a generic class extend multiple classes?通用 class 的类型如何扩展多个类? For example, say I have I generic that I want to be able to take objects that are subclasses of Melons or Berries, but not objects that are subclasses of other subclasses of Fruits?例如,假设我有一个泛型,我希望能够获取 Melons 或 Berries 子类的对象,但不能获取 Fruits 其他子类的子类的对象? I was thinking something like我在想类似的东西

public class MyGeneric<T extends Melons & Berries>

but this does not work as an interface is expected after the ampersand, not a class.但这不起作用,因为 & 符号后面的接口是预期的,而不是 class。 Additionally, online I saw the suggestion to make an interface and have T implement the interface, however I do not understand how to make an interface that specifies classes that can be accepted by a generic.另外,在网上我看到了创建接口并让 T 实现接口的建议,但是我不明白如何创建一个接口来指定可以被泛型接受的类。

& means and . &表示 T extends Melons & Berries means that T must be some type that extends both . T extends Melons & Berries意味着 T 必须是扩展两者的某种类型。 You evidently want it to mean or .您显然希望它表示 It doesn't.它没有。 And <T extends Melons | Berries> <T extends Melons | Berries> <T extends Melons | Berries> is not legal java syntax. <T extends Melons | Berries>是不合法的 java 语法。 For good reason - that would be useless.有充分的理由 - 那将是无用的。

You may think: Wait, you can't extend 2 things.你可能会想:等等,你不能扩展两件事。 Yes, you can - extends in generics refers solely to supertypes;是的,您可以 - 在 generics 中extends仅指超类型; it's like a combination of extends and implements .它就像extendsimplements的组合。

For example:例如:

void test(List<? extends Serializable & CharSequence> items) {
}

can be invoked by passing a List<String> .可以通过传递List<String>来调用。 That's because String is a subtype of Serializable , and also a subtype of CharSequence .那是因为StringSerializable的子类型,也是CharSequence的子类型。

The 'point' of this is that when you get an element from this list, you can treat it as either.这样做的“要点”是,当您从该列表中获取一个元素时,您可以将其视为两者之一。 Because it's and - it's a list of both.因为它是- 它是两者的列表。

There is no way in java to say: "I want to accept a list of Berries, or a list of melons, but not a list of Apples". java 中没有办法说:“我想接受一份浆果清单,或者一份甜瓜清单,而不是一份苹果清单”。 The reason there's no way to say that, is because its useless:之所以不能这么说,是因为它没用:

  • If there's a thing you can do to both melons and berries but not bananas, then whatever it is will have to be defined in an interface of sorts.如果你可以对甜瓜和浆果做某件事,但不能对香蕉做,那么无论它是什么,都必须在某种接口中定义。 Perhaps Melons and Berries both implement 'SeededFruit', and Banana doesn't.也许 Melons 和 Berries 都实现了“SeededFruit”,而 Banana 没有。 In that case, just write List<? extends SeededFruit>在这种情况下,只需编写List<? extends SeededFruit> List<? extends SeededFruit> isntead. List<? extends SeededFruit>不是。
  • If you just want to use aspects of melons and berries that are shared by all fruit (also bananas), just write List<? extends Fruit>如果您只想使用所有水果(包括香蕉)共享的瓜类和浆果的各个方面,只需编写List<? extends Fruit> List<? extends Fruit> - why put up arbitrary restrictions? List<? extends Fruit> - 为什么要设置任意限制?
  • If you want to write if (x instanceof Melons) doThing1; else if (x instanceof Berries) doThing2;如果你想写if (x instanceof Melons) doThing1; else if (x instanceof Berries) doThing2; if (x instanceof Melons) doThing1; else if (x instanceof Berries) doThing2; - java isn't 'meant' for that. - java 不是“故意的”。 There are tons of things java doesn't have that would be really convenient if everybody wrote code like that.如果每个人都编写这样的代码,那么 java 没有很多东西会非常方便。 But java doesn't have that, will not have that, folks don't usually write their java code like that.但是 java 没有那个,不会有那个,人们通常不会这样写他们的 java 代码。 Usually if someone does, they're writing very 'bad' code, in the sense that it is overcomplicated and/or hard to maintain and/or hard to adopt in the face of changing requirements, and needlessly so: You could write it differently and avoid those traps.通常如果有人这样做,他们正在编写非常“糟糕”的代码,因为它过于复杂和/或难以维护和/或在面对不断变化的需求时难以采用,而且不必要地这样:你可以用不同的方式编写它并避免那些陷阱。

The way I would do is to group the classes using an interface.我要做的方式是使用接口对类进行分组。 Then I use the interface to define the generic class.然后我使用该接口来定义通用的 class。 See below:见下文:

interface ForGenerics { }

class Fruit { }
class Melon extends Fruit implements ForGenerics {}
class Berry extends Fruit implements ForGenerics {}
class Apple extends Fruit {}
class MyGeneric<T extends ForGenerics> { }

public class Main{
    public static void main(String[] args) {
        MyGeneric<Melon> a;
        MyGeneric<Berry> b;
        
        // can't make MyGeneric of Apple
        //  MyGeneric<Apple> c;  
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM