使用Java接口作为参数强制实施严格(更好)类型安全的想法

时间:2014-10-31 05:34:17

标签: java generics interface type-safety

根据以下输入

更新 。我觉得对Java接口的类型安全使用的努力不是那么简单。

以下是我们想要做的一个简单示例:设计,跟随。在多次尝试获得类型安全性之后的实现时,我(再次)发现我们需要在Java中思考以鼓励Java支持我们的需求。我对原始示例进行了改进。我打开这个问题,因为可能有更好的方法来处理事情。

意图

  1. 想想我们想要放入哈希的一些不同的类。
  2. 我们希望将这些作为 ServiceProvider 接口实例的集合进行管理。
  3. 想法是制作这样的OO设计:
  4. 服务类型:

    public interface DisplaySettings    extends     ServiceInterface { ... }
    

    提供者类型:

    public interface ServiceProvider    extends     ServiceInterface { ... }
    

    实现:

        public class DisplayConfig extends Config  
                                   implements DisplaySettings, ServiceProvider 
        { ... }
    
    1. 当我们想要“注册”一个实现时,就会遇到挑战。这是 所需 方法的方法原型:

      public boolean registerService( final ServiceProvider newProvider )
      { ... }
      
      • newProvider实现的服务由以下内容给出:newProvider.getServiceInterface()
    2. 我们想把这种方法称为:

      ServicesMgr.registerServiceProvider( this );
      
    3. 感谢下面的建议,要求注册提供商的架构是指定接口:

      DisplaySettings videoSettings = ServicesMgr.getProvider( DisplaySettings.class );
      
    4. 当然,你不能这样做编译的唯一选择是使用“ .class ”来注册和查找提供程序实例对象。随着上面整洁定义的必要变化......

          DisplaySettings videoSettings = ServicesMgr.getProvider( DisplaySettings.class );
      

      这看起来更加类型安全。

      @immibis建议的获取提供者调用...

        public <InterfaceType extends ServiceInterface> ServiceProvider getProvider( Class<InterfaceType> interfaceClass )
        { ... }
      

      可悲的是,当需要查找时,该解决方案不允许HashMap“查找”提供程序。看起来哈希映射将使用不识别实现类的“类”。我尝试了一些变体,如:

        public Class<ServiceInterface>  getServiceType(){ ... }
      

      使用上面的InterfaceType。我对正在发生的事情的理解是,这是具有挑战性的,因为只有单一的继承。 Class不是:Class,其中:

        <InterfaceType extends ServiceInterface>
      

      目前我使用的是public Class getServiceType(){...},作为一致的密钥。当然,因为我们只是将“Class”转变为类型,所以它类型的空洞类型安全。通过将getServiceType包装在方法中,可以获得一些保护。

      继续从相关的示例中提取类型保护:

      看起来都不像我们正在寻找的东西()。这或某事可能接近吗?我正在寻找关于该怎么做的想法?非常感谢你的时间。

3 个答案:

答案 0 :(得分:2)

DisplaySettings videoSettings = ServicesMgr.getProvider( DisplaySettings.class );

是有效的代码,如果getProvider定义如下:

,则类型安全
public <InterfaceType extends ServiceInterface> InterfaceType getProvider(Class<InterfaceType> interfaceClass) {
    ...
}

这应该很容易实现。

您的registerServiceProvider方法在概念上看起来也很复杂,但我没有看到您提出的任何问题。

答案 1 :(得分:1)

我认为您需要的是Generic Method

在你的情况下,你可以这样做:

public interface ServicesMgr {

    public <E> E getProvider(Class<E> clazz);
}

然后你可以这样称呼它:

DisplaySettings displaySettings = mgr.getProvider(DisplaySettings.class);

这将强制执行类型检查,这是您想要的。 getProvider返回的对象需要是传递给它的Class的实例。

答案 2 :(得分:0)

您所描述的内容听起来像type-safe heterogenous container模式,但我不确定您是否可以使用接口。