不能使用不同类型的参数继承

时间:2018-09-17 22:36:23

标签: java generics

假设您有EntityService<E>PersonService extends EntityService<Person>EmployeeService extends EntityService<Employee>等。现在,假设您想创建一个SuperService来聚合其他服务,这些服务将暴露给外部世界。由于泛型擦除,您无法编写SuperService extends PersonService, EmployeeService,...如果不为每个服务编写特定的方法名称,有什么方法可以解决此问题?

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 {}

当前,我正在SuperInterface中编写特定的方法,这些方法在SuperInterface实现中委派给基础服务。更具体地说,我很好奇,是否有一些注释处理器能够以最小的努力生成工作服务接口。

2 个答案:

答案 0 :(得分:2)

您的意思是您想要此API的单入口,因此您的SuperService。如果是这样,并且您不介意进行投射:

  1. 将服务存储在Map
  2. 要求客户端指定他们要访问的内容。

这允许轻松存储服务,以及访问客户端所需实体的简单方法。

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);
    }
}

这缺乏类型安全性。但是,您可以通过以下方式实现类型安全性:

  • 正确的类型绑定:每个实体应共享一个公共类型
  • 通过访问者模式(反对instanceof类型检查,或更糟糕的是:没有实际的类型检查)实施多次调度。

您现在可以将服务真正封装在您的API中:客户端仅知道实体,而不是用于获取该实体的实际服务。

客户端将使用以下方法:

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

答案 1 :(得分:1)

以您尝试执行的方式是不可能的,对于从不同类型实现/继承的类型,对于这些类型存在多个具有相同签名的方法,实现/继承的类型只有该方法的一个版本,只要签名的返回类型不同,只要存在兼容性问题,就会在编译时提示。