抛开问题的质量:
您有一个包含方法calculateSomething() 的Shape 类。
Shape 没有定义特定的形状,所以很可能您可以返回 -1 或 0?
现在,我们可以确定 Shape 类的方法没有为我们提供任何真实的值/信息。即使你创建了一个Shape shape = new Shape() 对象并调用它的方法,它对我们一点帮助也没有。
相反,它为我们提供了一个方法,每个子类都必须重写该方法才能获得预期的结果。
这是什么意思以及它是如何工作的?
为了让您不必总是为每个类和对象执行Rectangle rect = new Rectangle(),矩形成为了 Shape 类的子类。
这使您可以稍后执行Shape rect = new Rectangle()。
这样做的最大好处是您创建了一个抽象机制,这意味着您有很多形状,无论是矩形还是三角形等,但最终它们都是 Shape 对象。
所以以后你可以这样做:
Shape rect = new Rectangle();
Shape triangle = new Triangle();
rect.calculate();
triangle.calculate();
而不是更细致:
Rectangle rect = new Rectangle();
Triangle triangle = new Triangle();
rect.calculate();
triangle.calculate();
前者可进一步用于:
// Putting all the objects in a list
List<Shape> shapes = new ArrayList<>();
// Create objects and add them
Shape rect = new Rectangle();
Shape triangle = new Triangle();
shapes.add(rect);
shapes.add(triangle);
正如您自己所见,处理和遍历所有元素均为 Shape 类型/类的列表更容易。
// Basic example
for (Shape shape : shapes)
shape.calculateSomething();
想象一下,如果你有一百种不同的形状,除了矩形和三角形。后一种方法在不使用继承的情况下,很快就会在不断的维护和代码更改试验中消耗您的项目。
通过其他方式利用继承,您可以根据需要增加 Shape 类的数量,并且过去适用于 Shape 的相同方法仍然适用于所有未来的新对象。
它在实践中是如何工作的?如何创建子类?
如您所知,您可以通过extend 关键字链接您的课程。
但这仅仅是开始。
为了能够利用继承,您必须在子类中覆盖您选择的方法。
以前面的例子为例:
Shape rect = new Rectangle();
rect.calculate();
但这提出了一个问题,当Shape 类从它返回-1 或0 并且rect 变量现在是Shape 类型时,如何获得calculate() 方法的正确值?
您可以轻松地通过@Override 标记覆盖父类的方法,并在子类上再次实现相同的方法,但计算方式不同。示例:
class Shape {
public void calculate() { return 0; }
}
class Rectangle extends Shape {
@Override
public void calculate() { return 2; }
}
注意方法的名称、变量等必须相同。
现在的情况是:
Shape rect = new Rectangle();
rect.calculate();
calculate() 方法将返回数字 2。
这是因为即使rect 对象的类型是Shape,它也是Rectangle。每个矩形都是一个形状。所以当你尝试调用想要的方法时,程序就知道选择了 Rectangle 类的重写方法,因为本质上它是一个 Rectangle,被抽象的 Shape 所覆盖。
这适用于任意数量的 Shape 子类,每个子类都有自己独特的方法实现。
另请注意,Rectangle 子类可以有自己的私有字段,用于其他方法:
class Rectangle extends Shape {
private int height;
private int width;
// constructor
public Rectangle(int h, int w) {
this.height = h;
this.width = w;
}
@Override
public void calculate() {
return this.w * this.h;
}
}
因此,要回答您的问题,您只需根据需要覆盖每个类所需的方法。如果一个方法没有被覆盖,则运行原来的Shape父类。
我希望这能为您对抽象和继承的困惑带来一点启发。
PS:
我知道您可能会感到困惑,但是那里有数百个答案和论坛来解释这个确切的事情,而这就是我们所有人的学习方式。不幸的是,这需要时间,但如果你自己看一些东西,你就会有更深入的理解。我敢肯定,您已经尝到了在这里提出的“错误”或“不好”的定义,并且考虑到需要材料,您将来会更容易自己研究它。我只是想与您联系,因为我一直在您的位置上,并相信我可以通过我的方法有所作为。
如果您有任何其他要添加或要更正的内容,随时欢迎在 cmets 部分中提出。
编辑:
正如另一个回答的人所提到的,Shape 类可以而且应该是一个抽象类。我只是假设你希望它是一个普通的。