Java 抽象类和toString()方法

Java 抽象类和toString()方法,java,abstract,tostring,Java,Abstract,Tostring,对于如何设置TestHomeline方法,以便在使用toString()方法时正确打印,我有点困惑。现在,当我运行main方法时,它会打印“null-0”,但我希望它说的是“Math-6”。这个程序应该扩展一个抽象类。它应该说有多少页是做家庭作业的,是做什么科目的 public abstract class Homework { private int pagesToRead; private String typeHomework; { // ini

对于如何设置TestHomeline方法,以便在使用toString()方法时正确打印,我有点困惑。现在,当我运行main方法时,它会打印“null-0”,但我希望它说的是“Math-6”。这个程序应该扩展一个抽象类。它应该说有多少页是做家庭作业的,是做什么科目的

public abstract class Homework {

    private int pagesToRead;
    private String typeHomework;

    {
        // initialise instance variables
        pagesToRead = 0;
        typeHomework = "none";
    }

    public Homework(int pages, String hw) {

        this.pagesToRead = pages;
        this.typeHomework = hw;

    }

    public abstract void createAssignment(int p);

    public int getPages() {
        return pagesToRead;
    }

    public void setPagesToRead(int p) {
        pagesToRead = p;
    }

    public String getTypeHomework() {
        return typeHomework;
    }

    public void setTypeHomework(String hw) {
        typeHomework = hw;
    }

}

public class MyMath extends Homework {

    private int pagesRead;
    private String typeHomework;

    public MyMath(int pages, String hw) {
        super(pages,hw);
    }

    public void createAssignment(int p) {
        setTypeHomework("Math");
        setPagesToRead(p);
    }

    public String toString() {
        return typeHomework + " - " + pagesRead;
    }
}

public class TestHomework {

    public static void main(String[] args) {
        MyMath one = new MyMath(6, "Math");
        one.createAssignment(6);
        System.out.println(one);
    }

}

派生类有自己的
类型作业
页面阅读
字段,这些字段从未设置(即使基类碰巧有同名字段)。因此,它们保持
null
0


您应该通过公共getter方法删除这些字段并使用基类中的数据。

这是因为您正在定义两个属性(其中一个属性恰好与抽象类的一个属性同名),但您没有初始化它们,而是在初始化抽象类的属性。(因此其值始终设置为其类型的默认值)

您需要从
MyMath
类中删除它们,并在抽象类中定义
toString
方法:它是默认情况下由其继承类使用的方法

public abstract class Homework {

    private int pagesToRead;
    private String typeHomework;

    // Same code

    // Define the toString here
    @Override
    public String toString() {
        return typeHomework + " - " + pagesToRead;
    }
}

public class MyMath extends Homework {

    // You don't need to define any extra attributes

    public MyMath(int pages, String hw) {
        super(pages,hw);
    }

    public void createAssignment(int p) {
        setTypeHomework("Math");
        setPagesToRead(p);
    }
}


public static void main(String[] args) {
    // Calls the constructor of the MyMath class, which in turn
    // invokes the constructor of its superclass, the 'Homework' class
    MyMath one = new MyMath(6, "Math");
    one.createAssignment(6);

    // Invokes the toString of the MyMath class. Since it does not have one,
    // The toString method of its superclass (Homework) is called.
    System.out.println(one);
}
为什么它不起作用: 请小心,您重新声明了父类的属性
typehomography
。属性会自动添加到扩展类中,因此您无需再次编写它们。
通过重新说明它,您混淆了编译器,在调试中查看您的代码表明,您的
one
对象包含您的
类型作业两次:

typeHomework = null // The one from the super class
typeHomework = "Math" // The one from your child class
您的方法现在使用超类中的
类型作业
,因此输出为空

pagesRead
为0,因为在调用
setPagesToRead(p)时,您正在将您的超类的
pagesToRead
设置为6(而不是
pagesRead
!)


一些风格小贴士 当重写以下方法时,请使用
@Override
注释:

@Override
public void createAssignment(int p) {
    setTypeHomework("Math");
    setPagesToRead(p);
}
实际上并不需要它,但这是一种很好的做法(代码的读者知道它会覆盖某些内容)。

在引用类的属性时,最好使用
this
语句,这样就可以清楚地看到,您引用的是属性而不是局部变量:

@Override
public String toString() {
    return this.typeHomework + " - " + this.pagesRead;
}

您应该使用
@Override
@SLaks技术上它不是严格需要的,没有它也可以工作。但这肯定是一个好的做法。@Tunaki:是的;这就是我写评论而不是回答的原因。我应该在哪里设置它们的值?在main方法中还是在MyMath类中?@tech404:你不应该。你不应该有重复的字段,这就是为什么你有一个基类——把你的toString方法移到基类。