【问题标题】:Square is not abstract and does not override abstract method area() in Shape class Square extends Shape{Square 不是抽象的,并且不会覆盖 Shape 类中的抽象方法 area() Square extends Shape{
【发布时间】:2021-10-02 05:50:32
【问题描述】:

我正在尝试为 Sololearn 上的一个项目找出抽象,然后我到达了模块 5。我被要求创建两个类(Square 和 Circle),它们的构造函数都采用参数并设置一个从抽象类继承的抽象方法为了计算面积。我觉得自己真的很愚蠢,因为我无法弄清楚我做错了什么。首先,我尝试在该方法上方编写@Override,因为我认为它会起作用。其次,我尝试将重写的抽象方法的返回类型从 int/double 更改为 void,但在我看来它没有任何意义,因为它应该返回一个数字,无论是 int 还是 double。无论如何,这是代码,希望有人可以阐明这个困境:

import java.util.Scanner;

abstract class Shape {
    int width;
    abstract void area();
}
//your code goes here
class Square extends Shape{

    int area(int width){
        return width*width;
    }

    Square(int width){
        width = width;
    }
}
class Circle extends Shape{

    double PI = 3.14;
    double area(int width){
        return PI*width*width;
    }

    Circle(int width){
        width = width;
    }
}

public class Program {
    public static void main(String[ ] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();
        int y = sc.nextInt();
        
        Square a = new Square(x);
        Circle b = new Circle(y);
        a.area();
        b.area();
    }
} 

【问题讨论】:

  • 你为什么编辑问题的代码而不更改任何文本?现在文本不再描述代码并且现有问题现在似乎是错误的(因为您修改了他们引用的代码)。
  • 对不起,我也会编辑文字
  • 第一次在这里发帖,对网站不熟悉
  • @MihailescuFanush 出于 Joachim Sauer 指出的原因,我回滚了您的编辑。
  • 昨天忘了非常感谢您的帮助。作为一名初级程序员,我经常发现自己试图理解我写的每个单词的作用,却无法放大并简单地思考这一点,所以我真的很感激

标签: java class inheritance abstract abstraction


【解决方案1】:

您声明抽象area 方法不接受任何参数并返回void

然后你在每个类中声明了一个不同的 area 方法。它们是不同的,因为它们接受参数并返回与声明的抽象方法不同的类型。

要完成这项工作,您应该让所有方法返回相同的类型并接受相同种类和数量的参数。我建议声明抽象方法不接受参数并返回double,如

abstract double area();

它不应该接受任何参数,因为它需要什么取决于子类(例如,在正方形的情况下,边尺寸就足够了,但在矩形的情况下就不行了)。所以子类中的方法实现应该使用子类本身的成员变量来计算面积。


顺便说一句,您的构造函数什么都不做,因为您将它们的参数分配给它们自己。您的类中需要一个成员变量,并且需要在构造函数中使用this 为它们赋值。比如

class Square extends Shape {

    private int width;

    Square(int width) {
        this.width = width;
    }

    @Override
    double area() {
        return width * width;
    }
}

最后,请记住,您在 Circle 类中称为 width 的不是圆的宽度,而是它的半径,因此请相应地命名该成员变量。

编辑 关于您对方法参数的评论:

关键是,目前您有两个子类,它们只需要一个参数来计算面积(正方形的宽度,圆的半径)。但是,如果明天您需要 Rectangle 课程怎么办?要计算它的面积,您需要两个参数,因此您需要有两个 area 方法。一个接受一个参数,另一个接受两个。撇开这个关于形状的特定示例不谈,该解决方案无法扩展,并且首先会消除使用继承(或对接口进行编程)的任何优势,特别是 polymorphism,即能够执行以下操作:

Shape s = new Square(5);
System.out.println(s.area());

然后只更改 s 的声明而不更改其余代码

Shape s = new Rectangle(5, 3);
System.out.println(s.area());

这个小例子并不能真正说明这个属性有多大帮助。如需更完整的说明,请查看What does it mean to "program to an interface"

所有这一切都表明使用对象的内部状态来进行在子类之间变化的计算是有帮助的,而不是在计算的内容取决于对象的属性时将可能可变数量的参数传递给它们的方法(即它的状态)而不是一些外部变量。

【讨论】:

  • 您好,根据您的建议,我对代码做了一些修改。我认为最初的问题不希望我更改抽象方法的定义。无论如何,我确实更改了构造函数、方法体并定义了一个类变量,但现在我没有得到任何输出......
  • 方法不是应该获取参数吗?
  • @MihailescuFanush 关于它什么也没显示的事实,你需要一个System.out.println 来打印调用方法的结果。简单地调用一个方法并不会打印它的结果。
  • @MihailescuFanush 关于参数,我编辑了我的答案,希望它更清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
相关资源
最近更新 更多