Ideas to enforce strict (better) type safety with a Java Interface as the parameter

核能气质少年 提交于 2019-12-13 04:48:03

问题


Update based on inputs below. Now and again I feel efforts for type-safe use of Java interfaces less than straightforward.

Here's a simple example of what we'd like to do: a design, following. When it comes to implementation after several attempts to get type safety, I'm (again) discovering that we need to think in Java to encourage Java to support our needs. I'm made improvements on the original example. I'm leaving the question open because there's probably a better way to go about things.

Intention:

  1. Think of some different classes we want to put in a hash.
  2. We want to manages these as a collection of ServiceProvider interface instances.
  3. The idea is to make an OO design like this:

Service type:

public interface DisplaySettings    extends     ServiceInterface { ... }

Provider type:

public interface ServiceProvider    extends     ServiceInterface { ... }

Implementation:

    public class DisplayConfig extends Config  
                               implements DisplaySettings, ServiceProvider 
    { ... }
  1. The challenge comes when we want to 'register' an implementation. This is a method prototype for the desired method:

    public boolean registerService( final ServiceProvider newProvider )
    { ... }
    
    • The service implemented by newProvider is given by: newProvider.getServiceInterface()
  2. And we'd like to call this kind of methods as follows:

    ServicesMgr.registerServiceProvider( this );
    
  3. Thanks to suggestions below, the schema to ask for the a registered provider is to specify the interface as so:

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

Of course, you can't do that ! The only alternative that compiles is to use the ".class" to register and look-up the provider instance object. Along with requisite changes to the tidy definitions above ...

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

Which looks a lot more type-safe.

The get provider call as suggested by @immibis ...

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

Sadly that solution won't allow the HashMap to 'find' the provider when it comes time to look it up. It looks like the hash map will use the "Class" which doesn't identify the implementation class. I have tried a few variations like:

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

And using the InterfaceType from above. My understanding of what's happening is that this is challenging because there's only single inheritance. Class is not: Class, where:

  <InterfaceType extends ServiceInterface>

At the moment I'm left with using: public Class getServiceType(){...}, as the consistent key. Of course since we are devolved to just "Class" as a type it kind of voids type safety. There's some protection by wrapping the getServiceType in a method.

Continuing to working on extracting type-protection from relevant looking examples:

  • Type-safe Hetrogenous Container Pattern
  • Enforcing parameter types on dependent interfaces?
  • In Java HashMap, how to enforce a generic type to be a subclass

Neither look like what we are looking for (yet). Is this or something close possible? I'm looking for ideas on how-to-do it? Many thanks for your time.


回答1:


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

is valid code, and type-safe, if getProvider is defined like this:

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

That should be easy enough to implement.

Your registerServiceProvider method also looks conceptually complex, but I don't see any questions you are asking about it.




回答2:


I think what you need is a Generic Method

In your case, you can do it like this:

public interface ServicesMgr {

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

Then you can call it like this:

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

This will enforce type checking, which is what you want. The object returned by getProvider will need to be an instance of the Class that you pass to it.




回答3:


What you are describing sounds like the type-safe heterogenous container pattern, but I'm not sure if you can do it with interfaces.



来源:https://stackoverflow.com/questions/26668135/ideas-to-enforce-strict-better-type-safety-with-a-java-interface-as-the-parame

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!