2016-11-16 53 views
0

我们假设我们有一个接口“I”和n个名为“C1”到“Cn”的“I”的实现。让我们进一步假设接口以及实现驻留在无法更改的外部库中。最后,让我们假设我们正在使用Java 8.

现在我们要扩展“I”的所有实现的功能。

如果“I”是可更改的,我们可以简单地向其添加默认实现的新方法,就像Oracle在推出流API时所做的那样。不幸的是,“我”是不可改变的。

我目前的解决方案如下:

创建一个新的接口“IX”,它扩展了“I”并包含所需的新方法作为默认实现。
因为“C1”到“Cn”没有实现“IX”而是“I”,我们需要实现“CX1”到“CXn”来使用新功能。这是我不喜欢的部分。我更喜欢一种像匿名类一样快速创建实现的方法。

这里有一些代码示例来说明我的方法:
有没有一种方法可以用比这少的代码来扩展现有的接口实现?

// Instantiate existing "C9" implementation of "I" 
I object = new C9(); 

// Definition of interface "IX" 
public interface IX extends I { 
    default void newMethod() { 
    // Do something 
    } 
} 

// Example definition of implementation "CX9" 
// Off course, this needs to be done for all "C1" to "Cn". 
public class CX9 extends C9 implements IX {} 

// Instantiate extended implementation "C9" 
IX object = new CX9(); 

因为“CX1”的定义为“CXN”不需要任何机构实施可言,我认为这些样板,并希望得到摆脱他们。我其实更喜欢类似以下的东西。

IX object = new (C9 implements IX)() {}; 

这当然不是有效的Java代码。这个想法是创建一个基于现有类(“C9”)实现额外接口(“IX”)的匿名类。有没有办法用标准的Java做到这一点?

我绝对想用标准的Java来做这件事,并且不需要字节码操作。当然,我可以使用包装器或动态代理,但“我”和“C”定义了很多方法。因此,我最终会得到更多的样板代码。

我承认这个问题纯粹是学术问题,因为最终它是关于在每个“I”实现中只删除一行代码。但我仍然对可能的解决方案感兴趣。

如果您喜欢更实用的方法,假设您希望在未知的实现集上实施类似流式API的内容,而无需更改底层接口。

感谢您对此的意见。

+0

所以你说所有你现有的Cn类只有一个默认的构造函数?那么所有这些都可以轻松地进行分类? – GhostCat

+1

@PavneetSingh不!没有! Code Review认为这些问题是假设的,这是[off-topic](http://codereview.stackexchange.com/help/on-topic)。 – Mast

+2

@PhilippSander看到上面的评论。我敢肯定,如果有人开始迁移,迁移将被拒绝。 Code Review不会接受它。 – Mast

回答

0

如果您不想“混入”接口,则具有空体的匿名类将完成这项工作。

IX object = new C9(){}; 

(假设C9已经实现IX

现在objectC9一个匿名子类的实例。

但如果C9自己尚未实现C9,没有纯粹的Java除了解决方案修改C9 ......这使得C9X不必要的。

但是请注意,修改C9也执行IX应该是良性的。首先,它不会破坏二进制兼容性。

1

解决此类事情的标准方法是代表团。因为我们不知道你的I也不C1 .. C9类型的任何东西,我将使用一个俗称接口示范:

public interface ExtSet<T> extends Set<T> { 
    default T reduce(BinaryOperator<T> op) { 
     Iterator<T> it = iterator(); 
     T t=it.next(); 
     while(it.hasNext()) t=op.apply(t, it.next()); 
     return t; 
    } 
    public static <T> ExtSet<T> enhance(Set<T> set) { 
     if(set instanceof ExtSet) return (ExtSet<T>)set; 
     final class Enhanced extends AbstractSet<T> implements ExtSet<T> { 
      public Iterator<T> iterator() { return set.iterator(); } 
      public int size() { return set.size(); } 
      public boolean contains(Object o) { return set.contains(o); } 
      public boolean add(T e) { return set.add(e); } 
      public boolean remove(Object o) { return set.remove(o); } 
     } 
     return new Enhanced(); 
    } 
} 

代表团实现必须做更多的工作比可能是空的延伸类体,但它只有做一次所有接口实现工作,甚至不知道他们,即

ExtSet<String> set1=ExtSet.enhance(new TreeSet<>()); 
Collections.addAll(set1, "foo", "bar", "baz"); 
System.out.println(set1.reduce(String::concat)); 

ExtSet<Integer> set2=ExtSet.enhance(new HashSet<>()); 
Collections.addAll(set2, 100, 42, 7); 
System.out.println(set2.reduce(Integer::sum)); 

ExtSet<Thread.State> set3=ExtSet.enhance(
           EnumSet.of(Thread.State.TERMINATED, Thread.State.NEW)); 
System.out.println(set3.reduce(BinaryOperator.minBy(Comparator.naturalOrder()))); 

这类似于如何checkedSet,synchronizedSetunmodifiableSet增强(或限制)现有的Set实现。

相关问题