Java 无法使用不同类型的参数继承

Java 无法使用不同类型的参数继承,java,generics,Java,Generics,假设您有EntityService,PersonService扩展EntityService,EmployeeService扩展EntityService等等。现在假设您想要创建一个聚合其他服务的SuperService,它将向外部世界公开。由于泛型擦除,您无法编写超级服务扩展PersonService,EmployeeService。。。有没有办法在不为每个服务编写特定方法名称的情况下解决这个问题 public interface EntityService<E> { E

假设您有
EntityService
PersonService扩展EntityService
EmployeeService扩展EntityService
等等。现在假设您想要创建一个聚合其他服务的
SuperService
,它将向外部世界公开。由于泛型擦除,您无法编写
超级服务扩展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 {}
公共接口实体服务{
E查找(长id);
...
}
公共接口PersonService扩展EntityService{}
公共接口EmployeeService扩展EntityService{}
//错误-无法使用不同类型的参数继承SuperService
公共接口超级服务扩展PersonService,EmployeeService{}

目前,我正在
SuperInterface
中编写特定的方法,这些方法被委托给底层服务。我很好奇,是否有一些注释处理器能够以最小的工作量生成工作服务接口。

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

您的意思是希望此API有一个单一的入口点,因此您的
超级服务。如果是这样,如果你不介意选角:

  • 将服务存储在
    地图中
  • 要求客户端指定要访问的内容
  • 这允许轻松地存储服务,并提供一种访问客户机所需实体的简单方法

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

    这不是你不能这么做的原因。您不能这样做,因为Java不支持多重继承。你到底想干什么?当有人使用
    SuperService
    时,你希望它是什么样子?@mypetlion他没有明确地说
    PersonService
    必须是一个类。如果这些类型是接口,他仍然会遇到他在文章中提到的问题。@Vinceeh可能再次更正,我只是想先弄清楚事实。对不起,如果我看起来过于热心,但是如果你知道我的意思的话,我有一些案例中问题不是问题。马托尼,听起来你想创造一个具有多重责任的物体。您能详细说明一下您的用例吗?@matoni即使没有接口,也不能创建只在返回类型上不同的重载。这不是继承的问题,甚至不是擦除的问题。您试图定义只在返回类型上不同的重载,这是不可能的。您需要有单独的方法标识符或参数。必须具有不同的属性,并且返回类型不是方法签名的一部分。那么,您已经拥有了不应更改的合同,格式为
    SuperInterface
    。如果我的理解是正确的,并且您将使用它来避免在多个模块中进行重大重构,那么我认为没有理由强迫它扩展2个较小的接口,因为您根本不打算使用它们。您只需进行组合,并将初始调用委托给每个单独的较小的服务实现。最后,如果您认为有另一个抽象层是有意义的,那么您可以在“SuperImplementation”中使用这两个委托接口@VinceEmigh的想法?听起来不错。我能看到的唯一问题是,除非我遗漏了什么,否则就是需要更改现有客户机以匹配新的方法签名。现在我考虑一下(将需要实际的确认),OP可能希望保持旧客户机的原样,但在新客户机中使用较小的API契约。如果是这样的话,也许我们从错误的角度看待解决方案。他可以为旧客户端保留现有接口,并将新接口注入到新创建的客户端中,而新实现将旧接口包装起来,以便只委托对其特定公开方法的调用。这打破了“超级接口”的约定,但我不得不承认这是一个很好的解决方案(+1)。
    SuperService service = new SuperService();
    Person person = service.find(50, Person.class);