簡體   English   中英

接口中的泛型類型和多態性

[英]Generic types and polymorphism in interfaces

我正在嘗試使用MyBatis生成對DB的一些調用,但是到目前為止,我遇到了麻煩。

假設我有以下實體和映射器:

public interface Entity {

    <T extends Entity> Class<Insertable<T>> mapper();
}

public interface Insertable<T extends Entity> {

    void insert(T entity);
}

public interface ClientMapper extends Insertable<Client> {

    void insert(Client client);
}

public interface CampaignMapper extends Insertable<Campaign> {

    void insert(Campaign campaign);
}

public class Client implements Entity {

    private final Long id;

    public Client(final Long id) {
        this.id = id;
    }

    @Override
    public <T extends Entity> Class<Insertable<T>> mapper() {
        return ClientMapper.class; // Incompatible types error
    }

我得到即使這個編譯錯誤ClientMapper的類型是Insertable<Client> ,是Client類型的Entity

目的是獲得以下類型安全的代碼:

public class MapperOperation {

    public static void insert(Entity entity) {
        insert(entity, entity.mapper());
    }

    private static <V extends Entity, K extends Insertable<V>> void insert(V entity, Class<K> mapperClass) {
        try (SqlSession session = PersistenceManager.get().openSession()) {
            K mapper = session.getMapper(mapperClass);
            mapper.insert(entity);
            session.commit();
        } catch (Exception e) {
            log.error("Could not insert entity {}", entity, e);
        }
    }
}

這樣,我可以使用任何Entity的實例調用方法insert ,然后要求他給我他的mapper以便我可以插入它。

這可能嗎? 難道我做錯了什么?

它應與以下更改一起編譯:

public interface Entity {
    <T extends Entity> Class<? extends Insertable<T>> mapper();
}    

// ...

public <T extends Entity> Class<? extends Insertable<T>> mapper() {
    return ClientMapper.class;
}

不能將Class<ClientMapper>分配給Class<ClientMapper> Class<Insertable<T>> ,出於相同的原因,也不能將List<Integer>分配給List<Number>

如果可以,那將是不安全的:

List<Integer> li = new ArrayList<>();
List<Number> ln = li; // does not compile
ln.add(3.14);
Integer i = li.get(0); // it's a Double!

編輯:這不是唯一的問題:該方法返回的內容取決於T ,但是您返回了另一個。 這個問題可以簡化:

class A {}
class B extends A {}
class C extends A {}

<T extends A> T getValue() {
    return new C();
}

在這里, T可能被解析為A任何子類型,因此我們無法返回C的實例,因為T可能被解析為B (例如,通過調用this.<B>getValue() ),並且C不是B的子類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM