我在Java中有一套相当复杂的泛型类.例如,我有一个界面
interface Doable{ X doIt(Y y); }
和实施
class DoableImpl implements Doable>,Foo >> { Foo > doIt(Foo > fooBZQ) { ... } }
在实际实现中,Doable
有不少方法Foo
等等,一遍又一遍地出现.(信不信由你,通用类型比这更痛苦.我为这个例子简化了它们.)
我想简化这些,以节省自己的打字和缓解眼睛的压力.我想是有一个简单的"类型的别名"对Foo
等的,说FooBBQ
和FooBZQ
.
我目前的想法是定义包装类:
class FooBBQ { public static FooBBQ valueOf(Foo> fooBBQ) { return new FooBBQ(fooBBQ); } private Foo > fooBBQ; private FooBBQ(Foo > fooBBQ) { this.fooBBQ = fooBBQ; } public Foo > toGeneric() { return fooBBQ; } } class FooBZQ { /* pretty much the same... */ } class DoableImpl implements Doable { FooBBQ doIt(FooBZQ fooBZQ) { ... } }
这很好用,但它有一些缺点:
我们需要为每个通用实例定义单独的包装器.包装器类很短且风格化,但我无法找到一种方法来宏观化它们.
我们有翻译的开销(概念,如果没有操作性)调用的valueOf
和toGeneric
之间进行转换FooBBQ
和Foo
.例如,如果doIt
调用某个期望a的库例程Foo
(实际的实现),我们最终会得到类似的结果
return FooBBQ.valueOf( libraryCall( fooBZQ.toGeneric() ) )
我们原本应该去的地方
return libraryCall(fooBZQ);
有没有其他方法来获得我想要的"类型别名"行为?也许使用一些第三方宏工具集?或者我是否需要接受我将不得不进行大量的输入,一种方式(使用实现中的泛型类型)或另一种方式(为它们编写包装器)?也许有这么多通用参数飞来飞去只是一个坏主意,我需要重新思考这个问题?
[更新]好的,我禁止任何进一步的"不要那样做"的答案.把它当作Foo
在我的问题域中具有真正价值的给定(Pete Kirkham可能是正确的,它具有足够的价值来获得具有描述性名称的正确包装类).但这是一个编程问题; 不要试图去解决问题.
如果你想要完全的类型安全,我认为如果没有某种包装类,你可以做得更好.但是,为什么不让这些类继承/实现原始的泛型版本,如下所示:
public class FooBBQ extends Foo> { ... }
这消除了对toGeneric()
方法的需要,在我看来,它更清楚,它只是一种类型别名.此外,可以在FooBBQ
没有编译器警告的情况下转换泛型类型.Foo, Bar, Baz...
如果可能的话,即使在实现中发生某些代码重复,我个人也会优先选择接口.
现在,在不知道具体问题域的情况下,很难说您是否需要,比如说FooBBQ
,在您的示例中,或者可能是:
public class FooBarextends Foo > { ... }
另一方面,您是否考虑过简单地配置Java编译器以不显示某些通用警告,而只是省略通用定义的部分?或者,战略性地使用@SuppressWarnings("unchecked")
?换句话说,你能DoableImpl
只做"部分通用化":
class DoableImpl implements Doable>,Foo > { Foo doIt(Foo foobar) { ... } }
并且为了减少代码混乱而忽略警告?再说一次,如果没有一个具体的例子,很难做出决定,但这是你可以尝试的另一件事.
Scala对类型别名有很好的支持.例如:
type FooBBQ = Foo[Bar[Baz,Qux]]
我意识到如果您没有切换到Scala的选项,这个答案将没有用.但如果您确实可以选择切换,那么您可能会有更轻松的时间.