Java泛型方法的继承和覆盖规则

发布于 2024-10-22 07:37:27 字数 879 浏览 6 评论 0原文

我有一个具有泛型方法的抽象类,我想通过用特定类型替换泛型参数来覆盖泛型方法。所以在伪代码中我有以下内容:

public abstract class GetAndParse {
  public SomeClass var;

  public abstract <T extends AnotherClass> void getAndParse(T... args);
}

public class Implementor extends GetAndParse {
  // some field declarations

  // some method declarations

  @Override
  public <SpecificClass> void getAndParse(SpecificClass... args) {
    // method body making use of args
  }
}

但由于某种原因我不允许这样做?我是否犯了某种语法错误,或者不允许这种继承和覆盖?具体来说,我收到有关 @Override 的错误,因为 eclipse IDE 不断提醒我实现 getAndParse

这就是我希望上面的代码如何工作。在我的代码的其他地方,有一个方法需要实现 GetAndParse 的对象实例,这特别意味着它们有一个我可以使用的 getAndParse 方法。当我在该实例上调用 getAndParse 时,编译器会检查我是否以正确的方式使用了 T 的特定实例,特别是 T应该扩展AnotherClass并且它应该是SpecificClass

I have an abstract class that has a generic method and I want to override the generic method by substituting specific types for the generic parameter. So in pseudo-code I have the following:

public abstract class GetAndParse {
  public SomeClass var;

  public abstract <T extends AnotherClass> void getAndParse(T... args);
}

public class Implementor extends GetAndParse {
  // some field declarations

  // some method declarations

  @Override
  public <SpecificClass> void getAndParse(SpecificClass... args) {
    // method body making use of args
  }
}

But for some reason I'm not allowed to do this? Am I making some kind of syntax error or is this kind of inheritance and overriding not allowed? Specifically I'm getting an error about @Override because the eclipse IDE keeps reminding me to implement getAndParse.

Here's how I want the above code to work. Somewhere else in my code there is a method that expects instances of objects that implement GetAndParse which specifically means that they have a getAndParse method that I can use. When I call getAndParse on that instance the compiler checks to see whether I have used specific instances of T in the proper way, so in particular T should extend AnotherClass and it should be SpecificClass.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

番薯 2024-10-29 07:37:27

我们这里有两种不同的方法,每个方法都有单独的类型参数。

public abstract <T extends AnotherClass> void getAndParse(Args... args);

这是一个带有名为 T 的类型参数的方法,并以 AnotherClass 为界,这意味着 AnotherClass 的每个子类型都可以作为类型参数。

public <SpecificClass> void getAndParse(Args... args)

这是一个带有名为 SpecificClass 的类型参数的方法,以 Object 为界(意味着每种类型都可以作为类型参数)。你真的想要这个吗?

Args 内部使用了类型参数吗?我想问题就在那里。


的含义

public abstract <T extends AnotherClass> void getAndParse(T... args);

是,方法的调用者可以决定使用哪种类型参数来调用该方法,只要这是AnotherClass的某个子类型。这意味着实际上可以使用 AnotherClass 类型的任何对象调用该方法。

由于调用者可以决定类型参数,因此您不能在子类中将参数类型缩小为 SpecificClass - 这不是该方法的实现,而是另一个同名的方法(重载) 。

也许您想要这样的东西:

public abstract class GetAndParse<T extends AnotherClass> {
  public SomeClass var;

  public abstract void getAndParse(T... args);
}

public class Implementor extends GetAndParse<SpecificClass> {
  // some field declarations

  // some method declarations

  @Override
  public void getAndParse(SpecificClass... args) {
    // method body making use of args
  }
}

现在 getAndParse 方法实现了父类的方法。

What we are having here is two different methods with individual type parameters each.

public abstract <T extends AnotherClass> void getAndParse(Args... args);

This is a method with a type parameter named T, and bounded by AnotherClass, meaning each subtype of AnotherClass is allowed as a type parameter.

public <SpecificClass> void getAndParse(Args... args)

This is a method with a type parameter named SpecificClass, bounded by Object (meaning each type is allowed as a type parameter). Do you really want this?

Is the type parameter used inside Args? I think the problem would be there.


The meaning of

public abstract <T extends AnotherClass> void getAndParse(T... args);

is that the caller of the method can decide with which type parameter he wants to call the method, as long as this is some subtype of AnotherClass. This means that in effect the method can be called with any objects of type AnotherClass.

Since the caller can decide the type parameter, you can't in a subclass narrow down the parameter type to SpecificClass - this would not be an implementation of the method, but another method with same name (overloading).

Maybe you want something like this:

public abstract class GetAndParse<T extends AnotherClass> {
  public SomeClass var;

  public abstract void getAndParse(T... args);
}

public class Implementor extends GetAndParse<SpecificClass> {
  // some field declarations

  // some method declarations

  @Override
  public void getAndParse(SpecificClass... args) {
    // method body making use of args
  }
}

Now the getAndParse method implements the parent class' method.

沉睡月亮 2024-10-29 07:37:27

您之所以会遇到此问题,是因为 Java 泛型中称为“擦除”的概念。
Java使用“擦除”来支持向后兼容性。即没有使用泛型的Java 代码。

擦除程序:
编译器将首先进行类型检查,然后尽可能地删除(擦除)所有类型参数,并在必要时插入 TypeCasting。

例如:

public abstract <T extends AnotherClass> void getAndParse(T paramAnotherClass);

会变成

public abstract void getAndParse(AnotherClass paramAnotherClass);

在类“Implementor.java”中,

代码

public <SpecificClass> void getAndParse(T paramAnotherClass)

​​会变成

public void getAndParse(SpecificClass paramAnotherClass){  }

编译器会看到你没有正确实现抽象方法。
抽象方法和实现方法之间存在类型不匹配。这就是您看到错误的原因。

更多详细信息可以在这里找到。
http://today.java.net/pub/a /today/2003/12/02/explorations.html

You are seeing this problem because of the concept called "Erasure" in Java Generics.
Java uses "erasure" to support backward compatibility. i.e Java code which did not use generics.

Erasure Procedure:
The compiler will first do a type checking and then it will remove(erase) all the type parameters as much as possible, and also insert TypeCasting where ever necessary.

example:

public abstract <T extends AnotherClass> void getAndParse(T paramAnotherClass);

will become

public abstract void getAndParse(AnotherClass paramAnotherClass);

In class "Implementor.java",

The code

public <SpecificClass> void getAndParse(T paramAnotherClass)

will become

public void getAndParse(SpecificClass paramAnotherClass){  }

the compiler will see that you have not implemented the abstract method correctly.
There is a type mismatch between the abstract method and the implemented method. This is why you are seeing the error.

More details can be found here.
http://today.java.net/pub/a/today/2003/12/02/explorations.html

格子衫的從容 2024-10-29 07:37:27

您不能覆盖特定类型T,因为实际上(如果您愿意,在字节码级别)由于类型擦除而只有一种方法getAndParse(请参阅其他答案)

public abstract void getAndParse(AnotherClass... args); // (1)

:每种类型的T,都使用相同的方法。

你可以重载它(我认为):

public void getAndParse(SpecificClass... args); // (2)

但这与(1)ant的方法没有什么不同,它将不会被通用代码调用:

T x = whatever;
object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass

You cannot override to specific type T because there is in fact (at the bytecode level if you wish) only one method getAndParse because of type erasure (see other answer):

public abstract void getAndParse(AnotherClass... args); // (1)

For every type of T, the same method is used.

You can overload it (I think):

public void getAndParse(SpecificClass... args); // (2)

but this will not a different method from (1) ant it will not be called by generic code:

T x = whatever;
object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass
浅忆 2024-10-29 07:37:27

不,这是无效的。如果拥有 GetAndParse 引用的人使用扩展 AnotherClass不同类来调用它,会发生什么?

No, it's not valid. What would happen if someone with a GetAndParse reference called it with a different class extending AnotherClass?

御守 2024-10-29 07:37:27

当有人引用类型 GetAndParse 并尝试调用 getAndParse 方法时,这就变得毫无意义了。如果 Cat 和 Dog 扩展 AnotherClass。我应该期望能够使用 Cat 或 Dog 调用 GetAndParse#getAndParse。但实现却试图限制它并使其兼容性降低!

That becomes a nonsense when someone has a reference to type GetAndParse and tries to call the getAndParse method. If Cat and Dog extend AnotherClass. I should expect to be able to call GetAndParse#getAndParse with either a Cat or a Dog. But the implementation has tried to restrict it and make it less compatible!

凡尘雨 2024-10-29 07:37:27

静态方法无法重写

class Vehicle{
static void park(int location){
    System.out.println("Vehicle parking..");
}}

class Car extends  Vehicle{
@Override //error
void park(int location) { //error
    System.out.println("Car Parking..");
}}

私有方法无法重写

class Vehicle{
private void park(int location){
    System.out.println("Vehicle parking..");
}
void callPark(){
    park(100);
}}

class Car extends  Vehicle{
//@Override
void park(int location) {
    System.out.println("Car Parking..");
}}

class Demo {
public static void main(String[] args) {
    Vehicle v1=new Car();
   v1.callPark();
}}

最终方法无法重写

class Vehicle{
final void park(int location){
    System.out.println("Vehicle parking..");
}}

class Car extends  Vehicle{
//@Override
void park(int location) { //error
    System.out.println("Car Parking..");
}}

Static method can't override

class Vehicle{
static void park(int location){
    System.out.println("Vehicle parking..");
}}

class Car extends  Vehicle{
@Override //error
void park(int location) { //error
    System.out.println("Car Parking..");
}}

Private method can't override

class Vehicle{
private void park(int location){
    System.out.println("Vehicle parking..");
}
void callPark(){
    park(100);
}}

class Car extends  Vehicle{
//@Override
void park(int location) {
    System.out.println("Car Parking..");
}}

class Demo {
public static void main(String[] args) {
    Vehicle v1=new Car();
   v1.callPark();
}}

Final method can't override

class Vehicle{
final void park(int location){
    System.out.println("Vehicle parking..");
}}

class Car extends  Vehicle{
//@Override
void park(int location) { //error
    System.out.println("Car Parking..");
}}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文