java—我的“runnable”实现无法解析已声明接口的对象上的方法

bbuxkriu  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(226)

这个问题在这里已经有了答案

使用泛型时无法解析方法(1个答案)
上个月关门了。
我有一个简单的问题 Runnable Java15实现。

package work.basil.example;

public class MonsterRunnable < Monster > implements Runnable
{
    private final Monster monster;

    // Constructor
    public MonsterRunnable ( Monster monster )
    {
        this.monster = monster;
    }

    @Override
    public void run ( )
    {
        this.monster.actOut(); // ? Compiler error: Cannot resolve method 'actOut' in 'Monster'
    }
}

我的ide(intellij 2020.3)中的编译器无法解析该方法 actOutthis.monster.actOut(); 生产线 run 方法。
但是该方法在接口上有明确的定义,如下所示。

package work.basil.example;

public sealed interface Monster
        permits Demon, Witch
{
    String name ( ); // This getter method implemented implicitly by `record` in our concrete classes `Demon` & `Witch`.

    public void actOut ( );  // ? Method is declared, yet cannot be resolved in `Runnable`. 
}

我的小演示应用程序使用java15预览特性jep360:sealed classes(预览)和jep384:records(第二次预览)。但我不明白这怎么会是麻烦的根源。
我想上面的代码应该足够回答这个问题了。但我可以展示接口的两个实现, Demon 以及 Witch .

package work.basil.example;

public record Demon(String name) implements Monster
{
    @Override
    public void actOut ( )
    {
        System.out.println( "This monster " + this.getClass().getSimpleName() + " named " + this.name + " buys a soul." );
    }
}

…还有…

package work.basil.example;

public record Witch(String name) implements Monster
{
    @Override
    public void actOut ( )
    {
        System.out.println( "This monster " + this.getClass().getSimpleName() + " named " + this.name + " casts a spell." );
    }
}

最后,这里展示了 actOut 工作方法- 如果我杀了线 this.monster.actOut(); 在冒犯中 run 方法。

package work.basil.example;

/**
 * Hello world!
 */
public class MonterMash
{
    public static void main ( String[] args )
    {
        System.out.println( "Hello World!" );
        MonterMash monterMash = new MonterMash();
        monterMash.demo();
    }

    private void demo ( )
    {
        Monster monster = new Witch( "Rowena" );
        System.out.println( "monster = " + monster );
        monster.actOut();
    }
}

运行时:
你好,世界!
怪兽=女巫[名字=罗维娜]
这个叫罗维娜的妖怪巫婆施了一个咒语。

pgpifvop

pgpifvop1#

签名 public class MonsterRunnable < Monster > implements Runnable 引入泛型参数 Monster 为了 MonsterRunnable . 泛型参数生成类。。通用。这意味着你可以用任何类型的类。
e、 g.当你使用 List<String> , <String> 是参数,元素的类型。 List 本身声明为 public interface List<E> extends Collection<E> . 注意 E 是泛型参数;类型的变量 List<String> 使用该参数引用 String s。您还可以引用 Integer 学生: List<Integer> . 你可以用 List 通过使用泛型参数,将任何元素类型作为泛型 E . E 表示“element”,是java约定:请参阅类型参数命名约定。 E 在中使用 List 表达方法等。
在你的例子中,泛型参数 Monster “隐藏”类型 Monster ,这是你的班级。引入的泛型类型 Monster 没有这个方法 actOut ,这是编译器告诉您的。
你想要的是 monster 属于扩展的类型 Monster ,简单继承。因此,只要删除泛型参数,就可以得到所需的:

public class MonsterRunnable implements Runnable

您在评论部分的注解:
整个实验的实际目标是为可运行的实现声明一个泛型类型。
你需要用 MonsterRunnable 是的实现 Monster :

package work.basil.example;

public class MonsterRunnable < T extends Monster > implements Runnable
{
    private final T monster;

    // Constructor
    public MonsterRunnable ( T monster )
    {
        this.monster = monster;
    }

    @Override
    public void run ( )
    {
        this.monster.actOut();
    }
}

现在 MonsterRunnable 通过使用 T ,限制扩展(实现) Monster .

相关问题