有界类型参数:覆盖时无法访问子类型方法

我刚开始在 Java 中使用有界类型,我不确定以下是否是由于继承使用不当或 javac 错误导致的编程错误


我需要定义两种不同类型的对象:必须管理的事物和那些事物的管理者。这就是为什么我创建了一个抽象类来模拟这些事物的常见行为

public abstract class AbstractThing {
    // Common method implemented
    public void hello() {
        System.out.println("HI,I'm AbstractThing");
    }
} 

和一个接口来定义那些东西的经理必须实现的方法

public interface AbstractManager {
    // Operation that a things' manager must implement
    public <T extends AbstractThing> void greet(T t);
}

所以假设我创建了两个具体的事物类,其中一个只是继承了抽象类:

public class Thing extends AbstractThing {
    // Constructor
    public Thing() {}
}

但另一个实现了自己的方法:

public class AnotherThing extends AbstractThing {    
    // Constructor
    public AnotherThing() {}
    
    // Extra method which this class implements
    public void goodbye() {
        System.out.println("BYE,I'm AnotherThing");
    }
}

但是当我如下定义经理时:

public class Manager implements AbstractManager {
    
    // Constructor method
    public Manager() {}

    // Implementation of the interface's method fails
    @Override
    public <AnotherThing extends AbstractThing>
    void greet(AnotherThing t) {
        // I can use this method,which AnotherThing inherits from AbstractThing
        t.hello();
        // But I can't use this one defined by AnotherThing
        t.goodbye();
    }

}

我收到错误:

AnotherManager.java:15: error: cannot find symbol
        t.goodbye();
         ^
  symbol:   method goodbye()
  location: variable t of type AnotherThing
  where AnotherThing is a type-variable:
    AnotherThing extends AbstractThing declared in method <AnotherThing>greet(AnotherThing)
1 error

我不明白为什么,因为它将类识别为 AnotherThing,但将其处理为 AbstractThing。我试图将对象转换为子类,但它不起作用

我还检查过它仅在我尝试访问子类型方法时发生,因为以下管理器编译并完美运行:

public class Manager implements AbstractManager {

    // Constructor method
    public Manager() {}
 
    // Implementation of the method defined into the interface
    @Override
    public <Thing extends AbstractThing>
    void greet(Thing t) {
        t.hello();
    }

    // I can overload the method "greet" without overriding the interface 
    // and it works for AnotherThing
    public void greet(AnotherThing t) {
        t.hello();
        t.goodbye();
    }

}

知道那里发生了什么吗?

iCMS 回答:有界类型参数:覆盖时无法访问子类型方法

这是为什么

enter image description here

不难弄清楚你是否做了这样的事情

library(dplyr)
library(knitr)

df %>% 
  mutate(across(hp,~ format(.x,big.mark = ","))) %>% 
  kable()

换句话说,“extends”之前的单词不应该是类名,而是通用标识符(变量名)。

在这种情况下,由于 T(或您称之为的任何人)是 AbstractThing,它不知道 goodbye() 是什么。

现在,为什么你的最后一个例子有效?

因为你说greet接收的是AnotherThing类型的对象,而不是像T这样的泛型类型。

, AnotherThing 中的

<AnotherThing extends AbstractThing>AnotherThing 类无关。它是一个类型参数的名称,就像它被称为 T 一样。它表现得像 AbstractThing 的原因是因为这就是我们所知道的。你的方法不知道它是如何参数化的;它只知道它得到了一个 AbstractThing 的子类。这对于我们需要捕获类型的构造很有用,但我们不关心它是什么子类型,例如:

<T extends AbstractThing> void copy(List<T> from,List<T> to) {
    for (T t : from) {
        t.hello();
        to.add(t);
    }
}

但是如果你想要一个专门的 AbstractManager 子类来管理 AnotherThing,类型参数应该在类上,而不是在方法上:

public interface AbstractManager<T extends AbstractThing> {
    // Operation that a things' manager must implement
    public void greet(T t);
}

public class AnotherManager implements AbstractManager<AnotherThing> {
    @Override
    public void greet(AnotherThing t) {
        t.hello();
        t.goodbye();
    }
}
本文链接:https://www.f2er.com/193171.html

大家都在问