我有一个function接受具有某些generic类型的参数


  公共字符串foo(T t){...}


现在... SomeA包含可以调用的一系列方法,例如baz1()baz2()baz3()等。

现在,这是擦


将传递给T的变量foo(T t)将是SomeBSomeC的实例,其中SomeB extends SomeASomeC extends someA
SomeBSomeC都包含返回glop(...)的方法SomeD,但是glop(...)不在SomeA中。
我希望能够传递foo(T t)以便它接受SomeBSomeC,但是,我需要调用glop(...)(例如,如下所示)


例如。

public < T extends SomeA > String foo(T t) {
    return t.glop().methodInsideOfSomeD().toString();
}


我宁愿不分别为fooSomeB(即SomeC fooSomeB)实现fooSomeC。我希望能够将此方法传递给提供SomeBSomeC的函数(甚至更好地包含方法glop(...)的任何东西)。

问题:我无法更改SomeBSomeC的实现或声明,因为它们驻留在我无法控制的库中。因此,我不能让它们都实现某些提供glop(...)的接口。

我只是运气不好吗?

最佳答案

请注意,使用您描述的签名定义通用方法几乎没有意义。如果类型参数T仅用作一个或多个参数的类型,则最好通过手动擦除它来简化操作:

public String foo(SomeA t) { /* ... */ }




无论如何,您至少要有满足您要求的以下替代方案:


用两个重载的替换一个foo(),一个重载的类型参数以SomeB为界,另一个重载的类型参数以SomeC为界。假设您没有其他SomeA子类型为此担心,考虑到SomeA没有glop(),这似乎是合理的。
foo()的实现中,使用instanceof运算符(或Class.isInstance())识别SomeBSomeC的实例,并对其进行适当的处​​理。
foo()中使用反射来确定参数的类是否提供具有期望签名的可访问glop(),如果是,则以反射方式调用它。


这些都不要求您以任何方式修改SomeASomeBSomeC。我知道您说过您不想做(1),但这很干净而且很容易。您应该考虑一下。


  我希望能够将此方法传递给提供甚至更好的包含方法glop(...))的函数。


那应该是(3),也许将参数类型更改为Object,但是我怀疑您是否真的想要那样。反射是混乱的,通常应避免反射。

10-08 00:07