java - Java泛型、接口和类继承
问题描述
考虑抽象类:
public abstract class Animal { ...}
和界面:
public interface Canine<T extends Animal> {...}
我已经定义了具体的类:
public class Dog extends Animal implements Canine<Dog> {...}
public class Wolf extends Animal implements Canine<Wolf> {...}
我想建立一个repository
访问动物数据库并返回它们的类。我用以下方式定义了它:
public interface Repository {
Option<Dog> findById(String id, Class<Dog> type);
Option<Wolf> findById(String id, Class<Wolf> type);
(注:Option
取自vavr
图书馆)
此存储库用于以下类:
public abstract AbstractFinderClass<T extends Animal & Canine<T>> {
private Class<T> animalType;
public AbstractFinderClass(Class<T> animalType) {
this.animalType = animalType;
}
public Option<T> findMyAnimal(String id) {
return repository.findById(id, this.animalType);
}
}
这又以具体的形式实现:
public class DogFinder extends AbstractFinderClass<Dog> {
public DogFinder() {
super(Dog.class);
}
}
现在,该行return repository.findById(id, this.animalType)
导致两个错误:
- 在第二个参数上,
this.animalType
是类型Class<T>
,而预期类型是Class<Dog>
,这些显然是不兼容的; - 返回类型应该是
Option<T>
while 而不是我得到Option<Dog>
恐怕我错过了一些“小”细节,正如我所期望的那样Dog
,并且T
是兼容的。你能帮我解决这个问题吗?
解决方案
第一个问题是你有一个不必要的类型参数DogFinder
。它是一个寻狗器,因此它所找到的类型参数是多余的(非常规命名的类型参数Dog
可能表明存在问题)。它应该是:
class DogFinder extends AbstractFinderClass<Dog> {
public DogFinder() {
super(Dog.class);
}
}
其次,您的Repository
类型具有绑定到特定类型的方法。这没有什么意义,因为您希望它是通用的。因此,您可以只使用一种方法,(可选)使存储库本身具有通用性(在解决签名冲突问题的过程中):
interface Repository<T extends Animal> {
Option<T> findById(String id, Class<T> type);
}
第三,除非我们缺少上下文,否则我相信您的Canine
类型不需要是通用的(除非事情必须令人费解):
interface Canine {
}
如果你需要一个专门的 canine finder,你可以简单地改变你的存储库类,如下所示:
abstract class CanineFinderClass<T extends Animal & Canine>
implements Repository<T> {...}
作为旁注,DogFinder
存储库是多余的,除非它提供特殊的狗方法,例如findAllPuppies()
. 否则,制作AbstractFinderClass
具体就足够了,因为类型是通用的(只是一个例子):
class AnimalFinderClass<T extends Animal> implements Repository<T> {
Repository<T> repository;
private Class<T> animalType;
public AbstractFinderClass(Class<T> animalType) {
this.animalType = animalType;
}
public Option<T> findMyAnimal(String id) {
return repository.findById(id, this.animalType);
}
}
推荐阅读
- verilog - Verilog 4位比较器结构模型
- sql - 使用外键将 XML 数据插入 SQL 表
- ios - 当通知中的数据更改时,SwiftUI 列表数据无法更新
- python - 遇到异常功能/输入验证问题
- reactjs - 如何在 rowinfo 反应表中再调用一个函数?
- flutter - MaterialPageRoute 与上下文有什么关系?
- elasticsearch - 当字段不是数组时,Integer.text 在 Kibana -7.9.2 中不再适用于查询字符串查询
- http-status-codes - 处理 REST API 服务器响应
- c - 应用程序(如用 C 开发的应用程序)是否应该添加容器(比如 docker)支持?
- node.js - 查找或查找一个在 mongoose 中返回空数组,但是当我在 mongo shell 中查询时,查找返回值