简体   繁体   English

泛型类型多态混淆?

[英]Generic type polymorphism confusion?

I have an abstract factory like so: 我有一个像这样的抽象工厂:

public abstract class DAOFactory {
    public abstract EntryDAO<EntryDTO> getEntryDAO();
    ...
}

With my DAO and DTO interfaces like so: 使用我的DAO和DTO接口如下:

public interface EntryDTO extends GenericDTO {
}

public interface EntryDAO<T extends EntryDTO> extends GenericDAO<T, Serializable> {  
}

And my implementation like so: 我的实现如下:

public class EntryDTOImpl implements EntryDTO {
}

public class EntryDAOImpl<T extends EntryDTO> extends GenericDaoImpl<EntryDTOImpl, ObjectId> 
 implements EntryDAO<T> {
}

Now, if I create a factory and override the getEntryDAO method like so: 现在,如果我创建一个工厂并覆盖getEntryDAO方法,如下所示:

public class MyDAOFactory extends DAOFactory {   
    @Override
    public EntryDAO<EntryDTO> getEntryDAO() {
        try {
            return new EntryDAOImpl<EntryDTOImpl>();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

I get a compile time error: 我得到一个编译时错误:

Type mismatch: cannot convert from EntryDAOImpl to EntryDAO 类型不匹配:无法从EntryDAOImpl转换为EntryDAO

EDIT 编辑

I've updated my abstract factory like so: 我像这样更新了我的抽象工厂:

public abstract <T extends EntryDTO> EntryDAO<T> getEntryDAO();

And made the change in my factory implementation: 并改变了我的工厂实施:

@Override
public <T extends EntryDTO> EntryDAO<T> getEntryDAO() {
    try {
        return new EntryDAOImpl<EntryDTOImpl>();
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Now I'm getting the compile time error: 现在我收到编译时错误:

Type mismatch: cannot convert from EntryDAOImpl<EntryDTOImpl> to EntryDao<T>

Define the abstract method this way (notice ? instead of T ): 以这种方式定义抽象方法(注意?而不是T ):

public abstract EntryDAO<? extends EntryDTO> getEntryDAO(); //should work for you

I recreated the scenario the way I understood it: returning subclass1<subclass2> as interface1<interface2> 我按照我理解的方式重新创建了场景: subclass1<subclass2>作为interface1<interface2>

For example, this works well: 例如,这很好用:

public static List<? extends CharSequence> dostuff1() { 
    return new ArrayList<String>();
}

But this doesn't work: 但这不起作用:

public <B extends CharSequence> List<B> dostuff2() {
    return new ArrayList<String>();
}

This gives the same compile-time error that you got: Type mismatch: cannot convert from ArrayList<String> to List<B> 这给出了相同的编译时错误: Type mismatch: cannot convert from ArrayList<String> to List<B>

The reason this is happening is that you're trying to return an EntryDaoImpl<EntryDTOImpl> , which is a subtype of EntryDao<EntryDTOImpl> , but not of EntryDao<EntryDTO> , which is the return type of the method. 出现这种情况的原因是,你试图返回EntryDaoImpl<EntryDTOImpl>这是一个亚型EntryDao<EntryDTOImpl>但不是EntryDao<EntryDTO>这是该方法的返回类型。

Solution: 解:

I believe you want to change the return type of the getEntryDao method to 我相信你想要将getEntryDao方法的返回类型更改为

EntryDAO<? extends EntryDTO> EntryDAO<? extends EntryDTO> . EntryDAO<? extends EntryDTO>

Just change the return type from EntryDao<T> to EntryDao<? extends T> 只需将EntryDao<T>的返回类型更改为EntryDao<? extends T> EntryDao<? extends T> . EntryDao<? extends T> That will do the trick: 这样就可以了:

@Override
public <T extends EntryDto> EntryDao<? extends T> getEntryDao() {
    try {
        return new EntryDAOImpl<EntryDTOImpl>();
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return dao;
}

Now as a justification, suppose EntryDao<T> has methods that return T like 现在作为理由,假设EntryDao<T>具有返回T方法

T load(Serializable id);

and methods that accept T like 以及接受T类的方法

void save(T t);

Now assume PersonDTO extends EntryDTO , and CarDTO extends EntryDTO . 现在假设PersonDTO extends EntryDTOCarDTO extends EntryDTO

If EntryDao<EntryDTO> were assignable from EntryDao<EntryDTOImpl> , it would also be assignable form EntryDao<PersonDTO> and EntryDao<CarDTO> . 如果EntryDao<EntryDTO>可从EntryDao<EntryDTOImpl>分配,则它也可以从EntryDao<PersonDTO>EntryDao<CarDTO>分配。

Then you could do: 然后你可以这样做:

EntryDao<EntryDTO> x = new EntryDao<PersonDTO>();       // currently this is a compile time error

If that were legal, you could do: 如果这是合法的,你可以这样做:

x.save(new CarDTO());   // a run time error, because x can only save Persons, not Cars

But what is EntryDao<? extends EntryDTO> 但什么是EntryDao<? extends EntryDTO> EntryDao<? extends EntryDTO> ? EntryDao<? extends EntryDTO> It is just EntryDao with all T -accepting methods like save(T) removed. 只有EntryDao,所有T -accepting方法,如save(T)被删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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