减少类型层次结构中的泛型变量的最佳实践?

时间:2015-04-21 19:21:20

标签: java generics

我想知道在包含类型层次结构和许多通用变量时是否有可能使java的泛型更具可读性和/或更易于使用。我还不熟悉java的泛型。在以下示例中可以执行的操作:

我们假设我需要以下课程......

abstract class BaseClass<T> {}

...使用以下课程的列表...

class Foo<T1, T2> {}

...并在此类情况下另外激活迭代器。

所以我会做以下事情:

class ImplClass<T1, T2> extends BaseClass<List<Foo<T1, T2>>> implements Iterator<Foo<T1, T2>> {}

我们还假设有一个处理BaseClass的接口:

interface Manipulator<T, B extends BaseClass<T>> {
  void doSomething(B baseClassInstance);
}

因此,当为ImplClass编写实现该接口的类时,我总是必须再次编写整个泛型签名,不是吗? 如下所示:

class ManipulatorA<T1, T2> implements Manipulator<List<Foo<T1, T2>>, ImplClass<T1, T2>> {
  @Override
  void doSomething(ImplClass<T1, T2> baseClassInstance) {...}
}
class ManipulatorB<T1, T2> implements Manipulator<List<Foo<T1, T2>>, ImplClass<T1, T2>> {
  @Override
  void doSomething(ImplClass<T1, T2> baseClassInstance) {...}
}

所以我可以提供一个EMPTY接口,它只用于类型转换以减少泛型变量:

interface ImplManipulator<T1, T2> extends Manipulator<List<Foo<T1, T2>>, ImplClass<T1, T2>>{
  // actually empty
}

并且实现看起来像:

class ManipulatorA<T1, T2> implements ImplManipulator<T1, T2> {
  @Override
  void doSomething(ImplClass<T1, T2> baseClassInstance) {...}
}
class ManipulatorB<T1, T2> implements ImplManipulator<T1, T2> {
  @Override
  void doSomething(ImplClass<T1, T2> baseClassInstance) {...}
}

拥有一堆空接口似乎对我来说不太可读。 不得不一直考虑巨大的通用签名。 在处理这种情况时,我能做些什么来产生更好的代码?

1 个答案:

答案 0 :(得分:0)

  

在处理这种情况时,我能做些什么来产生更好的代码?

改变语言......

java不支持类型别名或haskell样式的新类型。如果可以,请将scala添加到项目中。你可以混合使用scala和java。

另一种选择是使用某种源生成/预处理。甚至可能使用AST变换器。但这完全是习惯性的,所以如果不确切知道你的情况,很难给你任何建议

如果你必须坚持使用java,那么,正如你所注意到的,别名泛型类型的唯一方法是创建一个中间接口或类。您可以通过以下方式清理它:

  • 正确命名它们。 ImplManipulator并未向您提供更多信息,但FooListManipulator可能会有所帮助
  • 正确放置它们。如果您只创建内部子类,则不要使用空接口创建新文件 - 将其放在子类所在的同一文件中。如果只在一个包中创建子类,则创建一个类TypeAliases并将所有接口与包scoppe放在一起。如果您需要全局,请创建一个包typeAliases,将所有内容放在那里,永远不要再看那里

另一种选择是简单地删除泛型。人们经常使用hamcrest匹配器,因为他们的长签名会破坏可读性。在所有仿制药都要帮助你之后,不要让你的生活变得更加艰难(至少这是个想法)