接口,泛型和重构

时间:2014-03-08 01:28:53

标签: java generics refactoring

当你意识到你不懂Java时那个尴尬的时刻...

获得类A,B和C.它们都扩展了类X,它定义了UUID id,getId()和setId()

(旁注 - X及其与A,B,C和D的关系是固定的,不可更改)

编写相同的方法后

findA(UUID id, List<A> as)
findB(UUID id, List<B> bs)
findC(UUID id, List<C> cs)

,所有这些只返回一个匹配id的A(B,C),我觉得我需要做一些重构。

天真,我想 - 哦,我知道,我会让A,B和C实现一个接口,用Identifiable称它为UUID getId(),使用, mutatus mutandis ,来自findA的代码,并将其称为一天 - findIdentifiable(UUID id, List<Identifiable> list)将完成这些操作。

嗯,不;无法在List<A>(或<B><C>)上调用findIdentifiable。哎哟!有点尴尬,我没有看到它的到来 - 更糟糕的是,我甚至不明白它为什么不编译。

这是第一个问题。第二个问题是 - 进行这种重构的最佳方法是什么?因为路上有更多的课程,我不想写另一个相同的方法...

我在想“泛型”,但显然,尽管在简单的情况下使用泛型,我不知道如何处理这种情况。

2 个答案:

答案 0 :(得分:4)

你能做的是:

Identifiable findIdentifiable(UUID id, List<? extends Identifiable> list) {
    for (Identifiable ident : list) {
        if (ident.getId().equals(id))
            return ident;
    }
    return null;
}

因为你不能将通用参数子类化。

但是,由于您已经X扩展了ABC,为什么不用X代替是Identifiable

X findIdentifiable(UUID id, List<? extends X> list) {
    for (X ident : list) {
        if (ident.getId().equals(id))
            return ident;
    }
    return null;
}

答案 1 :(得分:1)

如果希望方法返回与列表类型相同的类型,则需要键入方法:

public <T extends Identifiable> T find(UUID id, List<T> items) {
    for (T item : items) {
        if (item.getId().equals(id))
            return item;
    }
    return null;
}

使用此签名,以下调用将在没有警告的情况下编译:

List<A> aList;
A found = find(id, aList);