简体   繁体   English

如果没有强制转换,则无法使用通用参数调用通用方法

[英]Calling a generic method with a generic parameter doesn't work without cast

First of all, sorry for the title but even after minutes of thinking, this was best I found. 首先,对标题感到抱歉,但是即使经过几分钟的思考,我仍然发现这是最好的。 Here the situation: 这里的情况:

I have an abstract 'Factory' class. 我有一个抽象的“工厂”类。 It takes T as return type of the instance. 它以T作为实例的返回类型。

abstract class Factory<T> {
    abstract T getInstance();
}

Now I add an interface to mark classes which have a factory. 现在,我添加了一个接口来标记具有工厂的类。 This interface is parameterized with the Factory itself. 该接口是使用Factory本身进行参数化的。

interface Factorized<TFACTORY extends Factory<?>> {}

Now I can mark classes that have a factory. 现在,我可以标记具有工厂的类。

class BaseImpl1 implements Factorized<BaseImpl1Factory> {}
class BaseImpl1Factory extends Factory<BaseImpl1> {
    @Override BaseImpl1 getInstance() { return null; /* TODO */}
}

With a small method and some reflection I can get an instance of the factory by passing the base class itself. 通过一个小的方法和一些反思,我可以通过传递基类本身来获得工厂的实例。

<RETURNED_FACTORY extends Factory<?>> RETURNED_FACTORY getFactory(Class<? extends Factorized<RETURNED_FACTORY>> clazz) {
    /* TODO */
}

// usage:
BaseImpl1Factory factory = getFactory(BaseImpl1.class);

This works fine until the point where I add generics in the base class . 直到我在基类中添加泛型为止,它都可以正常工作。

See the full example: 查看完整的示例:

public class Test {
    void test() {
        getFactory(BaseImpl1.class).someMethod1();
        getFactory(BaseImpl2.class).someMethod2();     // <-- compile error
        getFactory((Class<? extends Factorized<BaseImpl2Factory>>) BaseImpl2.class).someMethod2(); // <-- it works with cast
        getFactory(SubBase2Impl.class).someMethod2();  // only for info.. this works
    }

    <RETURNED_FACTORY extends Factory<?>> RETURNED_FACTORY getFactory(Class<? extends Factorized<RETURNED_FACTORY>> clazz) {
         /* TODO */
    }
}

abstract class Factory<T> {
    abstract T getInstance();
}
interface Factorized<TFACTORY extends Factory<?>> {}

// ****** implementation without generic *******
class BaseImpl1 implements Factorized<BaseImpl1Factory> {}
class BaseImpl1Factory extends Factory<BaseImpl1> {
    void someMethod1(){}
    @Override BaseImpl1 getInstance() { /* TODO */ }
}

// ****** implementation with generic *******
class BaseImpl2<T> implements Factorized<BaseImpl2Factory> {}
class BaseImpl2Factory extends Factory<BaseImpl2<?>> {
    void someMethod2(){}
    @Override BaseImpl2<?> getInstance() { /* TODO */ }
}

class SubBase2Impl extends BaseImpl2<String>{}

It works when I cast it but why do I have to? 它在我投放时有效,但是为什么必须这样做? What do I have to change to access the factory without casting? 在不进行铸造的情况下,我必须更改什么才能进入工厂?

Hints: 提示:

  • It is required to get the concrete instance BaseImpl1Factory and not only the abstract Factory instance when calling getFactory() because the factories have diffent methods and it should be needed to cast 调用getFactory()时,不仅要获取具体的实例BaseImpl1Factory,而且还需要获取抽象的Factory实例,因为工厂的方法不同,应该强制转换
  • Please don't care about the probably stupid plan behind this. 请不要在乎背后的愚蠢计划。 Actually the real problem is completely different but wanted to take out the business problem as much as possible 实际上,真正的问题是完全不同的,但希望尽可能解决业务问题

You're looking for what's called a self-type . 您正在寻找所谓的自我类型 Here's an example: 这是一个例子:

interface Factory<T> { T getInstance(); }

interface Buildable<T> { Factory<T> getFactory(); }

class CanBuild implements Buildable<CanBuild> {
  @Override
  public Factory<CanBuild> getFactory() {
    return null; // TODO
  }
}

The Buildable interface ( Factorized in your example) indicates a type that can build T s. Buildable接口(在您的示例中为Factorized )指示可以构建T的类型。 While T could be any type, you'll often use it as a self-type by making T the same type as the class being defined. 尽管T可以是任何类型,但是通过使T与要定义的类相同的类型,您经常将其用作自类型。

Self-types are commonly used when defining fluent interfaces . 自定义类型通常用于定义流畅的界面 The Truth library uses them heavily, so you might like to poke around their code to see more examples. Truth库大量使用它们,因此您可能想看看它们的代码以查看更多示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM