我很遗憾地说,我不能更多地向核心或更抽象地描述我的问题。我觉得解释我的问题的最好方法是通过这个非常具体的例子。
我想定义一个函数'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'。我看不出我怎么能避免这种情况。
请告诉我有更好的方法。 在某个地方,我想让我在后见之明中感到非常愚蠢。
答案 0 :(得分:2)
考虑从对象本身拆分解析/构造。在许多情况下,这两者是非常独立的问题。
你走在正确的轨道上,但我建议:
Readable
接口Readable
界面重命名为Reader
Reader
。 ReadCollection.read
方法的签名,以取Reader
而不是T
然后你会:
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()等的原因。
我仍然觉得这个解决方案不再那么难看了。
你们是否同意这是一个很好的解决方案?