简体   繁体   中英

Can not be inherited with different types arguments

Suppose you have EntityService<E> , PersonService extends EntityService<Person> , EmployeeService extends EntityService<Employee> and so on. Now suppose you want to create one SuperService aggregating other services, which would be exposed to outer world. Due of generics erasure, you can not write SuperService extends PersonService, EmployeeService , ... Is there any way how to solve this without writing specific method names for each service?

public interface EntityService<E> {
    E find(long id);
    ...
}

public interface PersonService extends EntityService<Person> { }
public interface EmployeeService extends EntityService<Employee> { } 

// ERROR - SuperService can not be inherited with different types arguments
public interface SuperService extends PersonService, EmployeeService {}

Currently I'm writting specific methods in SuperInterface which are delegated to underlying services. I'm curious, whether there is some annotation processor that is able to generate working service interface with minimal effort.

You're implying you want a single-entry point for this API, hence your SuperService . If so, and if you don't mind casting:

  1. Store the services in a Map
  2. Require the client to specify what they want to access.

This allows easy storing of the services, as well as a simple way to access the entity that the client wants.

class SuperService {
    private Map<Class<?>, EntityService<?>> services = ...;

    public SuperService() { //populate the map somehow..
        services.put(Person.class, new PersonServiceImpl());
        services.put(Employee.class, new EmployeeServiceImpl());
    }

    public <E> E find(long id, Class<E> type) {
        E service = services.get(type);
        if(service == null)
            throw new IllegalArgumentException("This API does not provide a service for the specified type.");

        return (E) service.find(id);
    }
}

This lacks type safety. However, you can implement type safety through:

  • Proper type binding: each entity should share a common type
  • Implementing multi-dispatch via the visitor pattern (opposed to instanceof type checking, or worse: no actual type checking).

You can now truly encapsulate the services in your API: the client only knows of the entities, not the actual service being used to obtain that entity.

The client would use this as follow:

SuperService service = new SuperService();
Person person = service.find(50, Person.class);

用您尝试做的方式是不可能的,对于从不同类型实现/继承的类型而言,存在多个具有相同签名的方法,对于该类型,实现/继承的类型只有方法的一个版本,无论何时签名仅在返回类型上有所不同,在编译时会提示兼容性问题。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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