在 Java 的抽象方法中使用继承的 类 识别方法的签名

Identify method's signature using inherited classes in Java's abstract methods

我知道这是一个很简单的问题,但我在Python工作了相当长的时间,现在我必须回到Java,我似乎有问题改变芯片 并围绕 Java 的基本多态性进行思考。

是否可以使用继承的 classes 之一作为参数覆盖(准确地说是实现)Java 中的 class' abstract 方法?

让我用一个非常简单的例子来解释(跟随 "almost official" example 的形状)

class Shape {}
class Circle extends Shape {}
class Triangle extends Shape {}

abstract class ShapeDrawer {
    abstract void draw(Shape s); 
}                       
class CircleDrawer extends ShapeDrawer {
    void draw(Circle c){
        System.out.println("Drawing circle");
    }
}

有没有办法让 Java 将 CircleDrawer class 中的 draw 方法识别为 draw 中抽象 draw 的实现17=]? (毕竟 Circle class 从 Shape 延伸)

否则:我想要的是 CircleDrawer class 的 draw 方法只接受类型 Circle 的实例,但同时, 我想告诉 Java 编译器 void draw(Circle c) 实际上是位于其父 class.

中的抽象方法 abstract void draw(Shape s) 的实现

提前谢谢你。

你可以通过泛型来解决你的问题:

public abstract class ShapeDrawer<T extends Shape> {
    public abstract void draw(T shape);
}

public class CircleDrawer extends ShapeDrawer<Circle> {
    public void draw(Circle circle) { ... }
}

不,Java方法签名必须完全匹配,不能使用子类型,否则会重载方法而不是覆盖它。

您可以 return 一个子类型,但仅此而已,return 类型不是方法签名的一部分。

你不能,而且有一个很好的理由说明你不能。拿下这份声明

public abstract class ShapeDrawer {
    public abstract void draw(Shape s); 
}

现在获取一些接收 ShapeDrawer 的代码并尝试使用它:

public void foo(ShapeDrawer drawer, Shape shape) {
    drawer.draw(shape);
}

这段代码应该可以工作,因为 ShapeDrawer 的声明承诺任何实现它的人都会提供一个名为 draw() 的方法,并且该方法可以处理任何 Shape.

但如果你被允许这样做:

public class CircleDrawer extends ShapeDrawer {
    public void draw(Circle c) {...}
}

这将不再适用,您的 CircleDrawer 将无法满足它可以处理任何 Shape 的承诺。


然而想象一下这个声明:

public abstract class ShapeCreator {
    public abstract Shape create();
}

public class CircleCreator extends ShapeCreator {
    public Circle create() {...}
}

这行得通吗?

是的,它会(前提是你使用 Java 5 或更高版本),因为与第一个声明不同,ShapeCreator 承诺的是它将有一个名为 create() 的方法,这将 return 一个 Shape。由于 CircleShapeShapeCreator 的子类只能决定 return Circle,没有违反承诺。


那么你如何实现你想要的呢?参见 :)

从技术上讲不是,但您可以针对您指定的功能对其进行修改。

public abstract ShapeDrawer {
    public abstract void draw(Shape s); 
}                       
public CircleDrawer extends ShapeDrawer {
    public void draw(Shape s){
        if (s instanceof Circle) {
            System.out.println("Drawing circle");
        }
    }
}