Java中的逆变型参数?

时间:2014-09-02 12:07:05

标签: java c# android generics

我正在考虑将此C#库移植到Java和Android

https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/tree/master/SignalR.EventAggregatorProxy.Client.DotNet

我想移植此界面

public interface IHandle<in T> where T : class
{
    void Handle(T message);
}

它需要处理Contravariance,以便它可以处理IHandle<ISomeIntefaceOrBaseClass>

之类的消息

该库的用户可以添加订阅者,当收到消息时,我会检查处理程序

subscribers
   .OfType<IHandle<T>>();

这可能与Java泛型有关,还是有更多的Java方式&#39;这样做?

1 个答案:

答案 0 :(得分:1)

我假设subscribers.OfType<IHandle<T>>();您希望所有订阅者都拥有IHandle<T>类型,其中T是邮件的类型,对吗?

在Java中,您必须稍微更改一下代码,因为因为类型擦除,您无法提供这样的类型。

假设每个类型/类都有一个句柄,你可以这样做:

interface IHandle<T> {
   Class<T> getMessageType(); //needed to query the handle for the supported class
   void handle( T message );
}

为了创建该界面的实现,您有几个选择:

为每个类创建一个实现:

class SpecialMessageHandle implements IHandle<SpecialMessage> {
  public Class<SpecialMessage> getMessageType() { return SpecialMessage.class; }

  public handle( SpecialMessage message ) { ... }
}

或者将该类作为参数传递:

class Handle<T> implements IHandle<T> {
  Class<T> messageClass;

  public Handle( Class<T> msgClass ) { messageClass = msgClass; }

  public Class<T> getMessageType() { return messageClass; }

  public handle( T message ) { ... }
}

然后你可能有一个地图消息类来处理类和处理订阅者类(例如Guava Multimap):

Map<Class<?>, IHandle<?>> handles = ...;
Multimap<IHandle<?>, Subscriber> subscribers = ...;

请注意,我在这里使用Class<?>,因为我不知道这些类是否有共同的超类或接口。如果您有一个共同的超类或界面X,那么您可以使用Class<? extends X>代替。

另外请注意,我使用IHandle<?>因为在Java中你无法定义地图,键和值需要使用相同的泛型类型,同时支持不同的键,即你可以&#39;执行Map<Class<T>, IHandle<T>>,其中每个键都是不同的T,但只允许符合键的值。

添加句柄如下所示:

handles.put( handle.getMessageType(), handle );

使用消息查询该地图将如下工作:

IHandle<?> handle = handles.get( message.getClass() ); 
Collection<Subscriber> handleSubscribers = subscribers.get( handle  );

请注意,如果您想获得超类的订阅者(例如,如果SpecialMessage extends Message并且您希望获得订阅Message的订阅者),那么您需要走上班级层次结构。

以下是您为一个级别做的事情:

handles.get( message.getClass().getSuperclass() );
for( Class<?> interface : message.getClass().getInterfaces() ) {
  handles.get( message );
}