【问题标题】:Implement generic methods from an interface without clutter?从一个没有混乱的接口实现泛型方法?
【发布时间】:2010-12-11 17:20:04
【问题描述】:

在实现这样的接口时,有什么方法可以避免将所有类型添加到类定义中的混乱?

MyInterface.java

import java.util.List;
abstract class BaseA {}
abstract class BaseB {}
abstract class BaseC {}

interface MyInterface<T extends BaseA, U extends BaseB, V extends BaseC> {
    public void foo( List<? extends T> list );
    public void bar( List<? extends U> list );
    public void baz( List<? extends V> list );
} 

MyImplementation.java

/* Some concrete implementations of the abstract classes used in the interface */
class A extends BaseA{}
class B extends BaseB{}
class C extends BaseC{}

class MyImplementation implements MyInterface<A,B,C> {
    public void foo( List<? extends A> list){}
    public void bar( List<? extends B> list){}
    public void baz( List<? extends C> list){}
}

我不喜欢的是我发现特定于方法的东西,例如参数的类型,与类声明混合在一起。在这种情况下,对于接口中的每个泛型方法,我必须在“括号部分”中添加一个正式类型。

是否有另一种方法来实现上述(强制实现的调用者在接口中使用参数类的特定子类)而不会出现所有“混乱”?

我对泛型不太感兴趣,上面的代码基本上是基于对这个question的回答。

【问题讨论】:

  • 如果有人想知道这样的构造有什么用途,建议您在这里查看最后一个答案:stackoverflow.com/questions/239645/… 上面的代码按预期工作,我只是想看看是否有一些无需所有额外语法即可实现此目的的其他方法。

标签: java generics


【解决方案1】:

这就是泛型的工作原理,但是如果您发现自己添加到一个很长的类型列表中,您可能会重新考虑您的设计。在这种情况下(实际上并不知道代码的用途),我会进一步概括接口:

abstract class PlayBase {}
interface MyInterface<T extends PlayBase> {
    public void playWith(List<T> list);
}   

...和一个示例实现:

class A extends PlayBase {}
class MyImplementationA implements MyInterface<A> {
    public void playWith(List<? extends A> list){}
}

这种方式设计更容易以一种很好的方式更改类型(无需更改界面)。

【讨论】:

  • 使用 playWithA/B/C 是函数名的糟糕选择。对于那个很抱歉。它们实际上并不意味着有任何共同点,只是一些随机的不同函数名称。通过使用更常见的“随机”名称 foo,bar,baz 来编辑答案以反映这一点 :)
【解决方案2】:

这个怎么样:

interface MyInterface {
    public <T extends BaseA> void playWithA( List<? extends T> list );
    public <U extends BaseB> void playWithB( List<? extends U> list );
    public <V extends BaseC> void playWithC( List<? extends V> list );
}   

【讨论】:

  • 一开始我是这样尝试实现的,但是这个接口并不能达到上述目的。
  • (续)由于类型擦除,您不能将 MyInterface 实现为: class MyImpl { public void playWithA( List extends T> list ); ... 等等 } 因此,MyImpl.playWitA() 必须接受 BaseA 的任何子类列表,而不仅仅是 A(这是一个既定目标)。
猜你喜欢
  • 1970-01-01
  • 2011-10-31
  • 1970-01-01
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多