Java继承和泛型

3

我有一些类看起来像这样:

模型

public abstract class BaseEntity<O extends Object> { ... }

public class Person extends BaseEntity<Person> { ... }

命令

public abstract class BaseCommand<BE extends BaseEntity<BE>> { ... }

public class PersonCommand extends BaseCommand<Person> { ... }

服务

public interface BaseService<BE extends BaseEntity<BE>> {
    public BE create(BaseCommand<BE> command);
}

public interface PersonService extends BaseService<Person> { ... }

服务实现

public abstract class BaseServiceImpl<BE extends BaseEntity<BE>> implements BaseService<BE> { }

public class PersonServiceImpl extends BaseServiceImpl<Person> implements PersonService {
    public Person create(PersonCommand personCommand) { ... }
}

PersonServiceImpl类无法编译。它没有识别出create()方法是从BaseService接口实现的。有人能告诉为什么PersonCommand在参数列表中没有被识别为一个BaseCommand<BE>吗?


我不明白为什么你要使用自身作为类的参数化... public class Person extends BaseEntity<Person> { ... } - I82Much
它们的返回类型可能不相同? - talnicolas
基本上我这样做是为了让BaseEntity中的方法可以引用该类型。public BE method(); 等等。 - Snowy Coder Girl
返回类型是正确的。当我使用Eclipse来重写/实现时,它将 Person 作为返回类型,它可以正常工作。它不会接受 PersonCommand 替代 BaseCommand<Person>。 - Snowy Coder Girl
@Rachel:没错,它不应该接受PersonCommand而不是BaseCommand<Person>。(请参阅我的答案以获取更多详细信息。:-)) - C. K. Young
这实际上与泛型无关。 - newacct
1个回答

7
当覆盖方法时,方法参数不是协变的(也就是说,子类必须接受超类也接受的类型,而不是更窄的类型)。这是因为人们可以通过PersonService接口使用您的PersonServiceImpl,该接口将接受类型为BaseCommand的参数,该参数未必是PersonCommand类型(想象一下如果您创建了第二个扩展BaseCommand的类)。
如果您让您的方法采用类型为BaseCommand的参数,则您的代码应该编译正确。

1
有道理。BaseServiceImpl类强制你接受所有BaseCommand<Person>对象。感谢帮助。+1 给一个好的解释和例子。 - Snowy Coder Girl
1
似乎要等4分钟才能让我接受,但我会的。再次感谢。 - Snowy Coder Girl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接