Java - 为继承特定接口的所有类添加功能

时间:2013-01-09 22:50:29

标签: java generics inheritance interface generic-collections

我很遗憾地说,我不能更多地向核心或更抽象地描述我的问题。我觉得解释我的问题的最好方法是通过这个非常具体的例子。

我想定义一个函数'readCollection',它将解析一个String并根据我调用该函数的方式给出一个特定类型的特定集合。

例如,我想这样使用它:

ArrayList<Foo> fb = readCollection("Foo1\n Foo2\n Foo3\n");

LinkedList<Bar> fb = readCollection("Bar1\n Bar2\n Bar3\n");

当然我已经为每个类定义了一个接口,它有一个用于读取一个实例的“读取”方法(“Bar ..”)。

我遇到了几个问题:

- 自然函数readCollection应该是一个静态函数,但是一个接口不能有静态方法。

- 方法readCollection应该返回一个类型为Foo或Bar或者类型的新对象,但我不能实例化类型',它通常在我定义的readCollection类中定义。

- 假设该方法没有静态定义,我不能在不引用该类型的特定对象的情况下调用它,由于前一点,我无法做到这一点。

如何在不为每个Foo和Bar等复制它的情况下编写我的方法?

我似乎自己找到了一个解决方案,但它非常难看和讨厌。

我现在有

public interface Readable<T> {
    public T read(String str); }

public class ReadCollection<T extends Readable<T>> {
    public Collection<T> read(File file, Collection<T> ts, T t) {
        ...
        ts.add(t.read(strLine));
        ...
        return ts; 
} }

public class Bars extends ReadCollection<Bar>{
    ...
    public static void main(String[] args) {
    new Bars().read(new File("fake/path"), new ArrayList<Bar>(), new Bar()); }

在这里,我发送了一个ArrayList的新实例,以返回结果,并为Bar,以便引用方法'read'。我看不出我怎么能避免这种情况。

请告诉我有更好的方法。 在某个地方,我想让我在后见之明中感到非常愚蠢。

3 个答案:

答案 0 :(得分:2)

考虑从对象本身拆分解析/构造。在许多情况下,这两者是非常独立的问题。

你走在正确的轨道上,但我建议:

  1. 不要让您的元素类型继承自Readable接口
  2. Readable界面重命名为Reader
  3. 为您要解析的每种类型实施Reader
  4. 更新ReadCollection.read方法的签名,以取Reader而不是T
  5. 然后你会:

    public class ReadCollection<T,C extends Collection<T>> {
        public C read(File file, C ts, Reader<T> reader) {
            ...
            ts.add(reader.read(strLine));
            ...
            return ts; 
        } 
    }
    

    这使您可以很好地分离应该解决您列出的所有问题的问题。

答案 1 :(得分:1)

API应通过接口定义。

共享实现应该通过抽象基类。

那么如何在不失去界面优势的情况下使用抽象基类呢?

轻松!只需要抽象基类实现接口。

然后,任何需要共享功能的类都可以扩展抽象基类,但是你不会将自己绑定到任何特定的实现,这对于编写单元测试很有用。例如。

答案 2 :(得分:0)

我很高兴我能告诉你,在你的评论(@stevevls)和朋友的帮助下,我已经找到了最终和最好的答案。

我现在有

public interface Reader {
    public Reader read(String str); }

所以我删除了泛型参数,shich是不必要的

public class ReadCollection { // no generic class!
public static <R extends Reader, C extends Collection<R>> // generic static function! 
        C readColl(File file, Class<? extends C> collClass, Class<? extends R> readClass) {
    C ts = collClass.newInstance()
        Reader t = readClass.newInstance()
        ...
        ts.add(readClass.cast(t.read(strLine)));
        ...
        return ts; 
} }

并且,现在我可以从任何地方调用该函数:

ArrayList<Point> l = ReadCollection.readColl(new File("examples/ex1.csv"), ArrayList.class, Point.class);

(假设Point实现Reader /具有读取方法......)

没有发送新实例,并且重要的是:无需在任何地方扩展类ReadCollection。

读取方法不能是静态的问题,导致它在接口Reader中定义,持续存在。这就是我使用readClass.newInstance()等的原因。

我仍然觉得这个解决方案不再那么难看了。

你们是否同意这是一个很好的解决方案?