我有一个function
接受一个generic
类型
public< T扩展了SomeA> String foo(T t){...}
现在...... SomeA
包含一系列可以调用的方法,例如baz1()
,baz2()
,baz3()
等等。
现在,请点击
将传递给T
的变量foo(T t)
将是SomeB
或SomeC
的实例,其中SomeB extends SomeA
和{{ 1}}。
SomeC extends someA
和SomeB
都包含方法SomeC
,返回glop(...)
,然而,SomeD
不是在glop(...)
。
我希望能够传递SomeA
,以便它接受foo(T t)
或SomeB
,但是,我需要调用SomeC
(例如, )
E.g。
glop(...)
我不想单独为public < T extends SomeA > String foo(T t) {
return t.glop().methodInsideOfSomeD().toString();
}
和foo
(即SomeB
SomeC
)实施fooSomeB
。我希望能够将此方法传递给提供fooSomeC
或SomeB
的函数(或者更好的包含方法SomeC
的任何内容)。
问题:我无法更改glop(...)
或SomeB
的实现或声明,因为它们位于我无法控制的库中。因此,我不能让它们都实现一些提供SomeC
的接口。
我只是运气不好吗?
答案 0 :(得分:2)
请注意,使用您描述的签名定义泛型方法几乎没有意义。如果类型参数T
仅用作一个或多个参数的类型,那么您也可以通过手动擦除它来简化操作:
public String foo(SomeA t) { /* ... */ }
在任何情况下,您至少都有符合您要求的替代方案:
将一个foo()
替换为两个重载的,一个类型参数以SomeB
为界,另一个类型参数以SomeC
为界。这假设您没有SomeA
的其他子类型为此目的担心,这似乎是合理的,因为SomeA
没有glop()
。
在foo()
的实施中,使用instanceof
运算符(或Class.isInstance()
)来识别SomeB
和SomeC
的实例,并处理适当的。
使用foo()
中的反射来确定参数的类是否提供了具有预期签名的可访问glop()
,如果是,则反复调用它。
这些都不要求您以任何方式修改SomeA
,SomeB
或SomeC
。我知道你说你不想做(1),但它很干净,很容易。你应该考虑一下。
我希望能够将此方法传递给提供包含方法glop(...)的任何内容的函数,甚至更好。
那可能是(3),也许参数类型改为Object
,但我怀疑你真的想要那样。反思很混乱,通常应该避免。
答案 1 :(得分:1)
根据我的理解,您将不得不复制该方法,但您可以通过分解公共部分来重用代码:
public < T extends SomeB > String foo(T t) {return fooX(t.glop());}
public < T extends SomeC > String foo(T t) {return fooX(t.glop());}
采用glop()
:
private String fooX(SomeD globResult) {
return globResult.methodInsideOfSomeD().toString();
}
我不知道为什么您无法更改SomeA
以使用默认实现(或方法)添加glob()
方法,但是如果您可以为您添加界面SomeB
/ SomeC
课程,比如ProviderOfSomeD
,你可以这样做:
public < T extends SomeA & ProviderOfSomeD> String foo(T t) {return fooX(t.glop());}
请注意,您可以使用此功能进行限制。
另一种Java 8方式(不需要任何更改):
public String foo(final Supplier<? extends SomeD> t) {return fooX(t.get());}
// calling them:
SomeB b = ...;
SomeC b = ...;
foo(b::glop);
foo(c::glop);