如何创建一个 Java 类来实现具有两种泛型类型的一个接口?
我有一个通用接口,
public interface Consumer<E> {
public void consume(E e);
}
我有一个消耗两种类型对象的类,所以我想做类似的事情:
public class TwoTypesConsumer implements Consumer<Tomato>, Consumer<Apple>
{
public void consume(Tomato t) { ..... }
public void consume(Apple a) { ...... }
}
显然我不能这样做。
我当然可以自己实现调度,例如
public class TwoTypesConsumer implements Consumer<Object> {
public void consume(Object o) {
if (o instanceof Tomato) { ..... }
else if (o instanceof Apple) { ..... }
else { throw new IllegalArgumentException(...) }
}
}
但我正在寻找泛型提供的编译时类型检查和调度解决方案。
我能想到的最好的解决方案是定义单独的接口,例如
public interface AppleConsumer {
public void consume(Apple a);
}
从功能上来说,我认为这个解决方案是可以的。它只是冗长和丑陋。
有什么想法吗?
I have a generic interface
public interface Consumer<E> {
public void consume(E e);
}
I have a class that consumes two types of objects, so I would like to do something like:
public class TwoTypesConsumer implements Consumer<Tomato>, Consumer<Apple>
{
public void consume(Tomato t) { ..... }
public void consume(Apple a) { ...... }
}
Apparently I can't do that.
I can of course implement the dispatch myself, e.g.
public class TwoTypesConsumer implements Consumer<Object> {
public void consume(Object o) {
if (o instanceof Tomato) { ..... }
else if (o instanceof Apple) { ..... }
else { throw new IllegalArgumentException(...) }
}
}
But I am looking for the compile-time type-checking and dispatching solution that generics provide.
The best solution I can think of is to define separate interfaces, e.g.
public interface AppleConsumer {
public void consume(Apple a);
}
Functionally, this solution is OK, I think. It's just verbose and ugly.
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
考虑封装:
如果创建这些静态内部类让您烦恼,您可以使用匿名类:
Consider encapsulation:
If creating these static inner classes bothers you, you can use anonymous classes:
由于类型擦除,您无法两次实现相同的接口(使用不同的类型参数)。
Because of type erasure you can't implement the same interface twice (with different type parameters).
这是基于 Steve McLeod 的解决方案的可能解决方案:
问题的隐含要求是
Consumer和共享状态的
Consumer
对象。对Consumer、Consumer
对象的需求来自于其他需要这些对象作为参数的方法。我需要一个类来实现它们以便共享状态。Steve 的想法是使用两个内部类,每个内部类实现不同的泛型类型。
此版本为实现 Consumer 接口的对象添加了 getter,然后可以将其传递给需要它们的其他方法。
Here's a possible solution based on Steve McLeod's one:
The implicit requirement of the question was
Consumer<Tomato>
andConsumer<Apple>
objects that share state. The need forConsumer<Tomato>, Consumer<Apple>
objects comes from other methods that expect these as parameters. I need one class the implement them both in order to share state.Steve's idea was to use two inner classes, each implementing a different generic type.
This version adds getters for the objects that implement the Consumer interface, which can then be passed to other methods expecting them.
至少,您可以通过执行以下操作对调度的实现进行一些小改进:
Fruit 是 Tomato 和 Apple 的祖先。
At least, you can make a small improvement to your implementation of dispatch by doing something like the following:
Fruit being an ancestor of Tomato and Apple.
刚刚偶然发现了这一点。碰巧,我遇到了同样的问题,但我以不同的方式解决了它:
不幸的是,我刚刚创建了一个像这样的新接口
,这被视为针对所有逻辑的
Consumer
而不是Consumer
。 您必须在类中为第二个消费者创建一个小型适配器,就像这样因此,如果需要
Consumer
, ,您可以简单地传递this
,如果>Consumer
需要,只需传递consumerAdapter
just Stumbled upon this. It just happened, that I had the same Problem, but I solved it in a different way:
I just created a new Interface like this
unfortunately, this is considered as
Consumer<A>
and NOT asConsumer<B>
against all Logic. So you have to create a small Adapter for the second consumer like this inside your classif a
Consumer<A>
is needed, you can simply passthis
, and ifConsumer<B>
is needed just passconsumerAdapter
在函数式风格中,在不实现接口的情况下很容易做到这一点,并且它还进行编译时类型检查。
我们使用实体的功能接口
我们的经理适当地处理和使用实体
In Functional style it is quite easy do this without implementing the interface and also it does the compile time type checking.
Our functional interface to consume entity
our manager to process and consume entity appropriately
您不能直接在一个类中执行此操作,因为由于删除泛型类型和重复的接口声明而无法编译下面的类定义。
将相同消耗操作打包在一个类中的任何其他解决方案都需要将您的类定义为:
这是毫无意义的,因为您需要重复/复制这两个操作的定义,并且它们不会从接口引用。恕我直言,这样做是一个糟糕的小代码重复,我试图避免。
这也可能表明一个类有太多的责任来消耗 2 个不同的对象(如果它们没有耦合)。
然而,我正在做的以及您可以做的是添加显式工厂对象以通过以下方式创建连接的消费者:
如果实际上这些类型确实耦合(相关),那么我建议以这种方式创建一个实现
:优点是工厂类知道这两种实现,有一个共享状态(如果需要),并且如果需要,您可以返回更多耦合的消费者。没有不是从接口派生的重复的消费方法声明。
请注意,如果每个消费者不完全相关,则它们可能是独立的(仍然是私有的)类。
该解决方案的缺点是类的复杂性较高(即使这可以是一个 java 文件),并且要访问使用方法,您需要再调用一次,因此
您不必:
总而言之,您可以定义一个顶级类中有 2 个通用消费者,使用 2 个内部类,但在调用时,您需要首先获取对适当实现消费者的引用,因为这不能只是一个消费者对象。
You cannot do this directly in one class as the class definition below cannot be compiled due to erasure of generic types and duplicate interface declaration.
Any other solution for packing the same consume operations in one class requires to define your class as:
which is pointless as you need to repeat/duplicate the definition of both operations and they won't be referenced from interface. IMHO doing this is a bad small and code duplication which I'm trying to avoid.
This might be an indicator also that there is too much responsibility in one class to consume 2 different objects (if they aren't coupled).
However what I'm doing and what you can do is to add explicit factory object to create connected consumers in the following way:
If in reality those types are really coupled (related) then I would recommend to create an implementation in such way:
The advantage is that the factory class knows both implementations, there is a shared state (if needed) and you can return more coupled consumers if needed. There is no repeating consume method declaration which aren't derived from interface.
Please note that each consumer might be independent (still private) class if they aren't completely related.
The downside of that solution is a higher class complexity (even if this can be a one java file) and to access consume method you need one more call so instead of:
you have:
To summarize you can define 2 generic consumers in one top-level class using 2 inner classes but in case of calling you need to get first a reference to appropriate implementing consumer as this cannot be simply one consumer object.
避免使用更多类的另一种选择。 (使用java8+的示例)
Another alternative to avoid the use of more classes. (example using java8+)
很抱歉回答旧问题,但是我真的很喜欢它!尝试这个选项:
我认为这就是您正在寻找的。
你得到这个输出:
Sorry for answer old questions, but I really love it! Try this option:
I think that is what you are looking for.
You get this output: