Discuss / Java / 问:为什么在Main中调用在PrimaryStudent中定义的getGrade()会报错呢??

问:为什么在Main中调用在PrimaryStudent中定义的getGrade()会报错呢??

Topic source

YANGZY1202

#1 Created at ... [Delete] [Delete and Lock User]
//Main.java
public class Main {

	public static void main(String[] args) {
		Person p = new Person("小明", 12);
		Student s = new Student("小红", 20, 99);
		// TODO: 定义PrimaryStudent,从Student继承,新增grade字段:
		Student ps = new PrimaryStudent("小军", 9, 100, 5);
		System.out.println(ps.getScore());
		
        //为什么在Main中调用在PrimaryStudent中定义的getGrade()会报错呢??
		System.out.println(ps.getGrade()); 
	}

}

//Person.java
...
//Student.java 
...
//PrimaryStudent.java
public class PrimaryStudent extends Student{
	
	protected int grade;
	
	public PrimaryStudent(String name, int age, int score, int grade) {
		super(name, age, score);
		this.grade = grade;
	}

	public int getGrade() {
		return grade;
	}

}

YANGZY1202

#2 Created at ... [Delete] [Delete and Lock User]

自己研究了一下,好像是因为Main中定义的ps实际上是一个Student的实例(向上转型)

	Student ps = new PrimaryStudent("小军", 9, 100, 5);

因此在Main中直接使用

  System.out.println(ps.getGrade()); 

编译无法通过——Student中并没有getGrade()方法,需要向下转型才可以通过编译:

 System.out.println(((PrimaryStudent) ps).getGrade());

但为什么这里向下转型是OK的呢?明明在子类PrimaryStudent中新增了grade相关字段和方法,为何Student ps可以向下转型为PrimaryStudent?

如果是因为Student ps定义时是new了一个 PrimaryStudent的对象,那么为什么我们又要说ps是一个Student实例呢?

......有点晕QAQ

YANGZY1202

#3 Created at ... [Delete] [Delete and Lock User]

再看了一遍廖老师的教程......好像弄明白了 /(ㄒoㄒ)/~~

Main中定义了一个Student实例ps(实际上是一个PrimaryStudent的实例,向上转型成一个Student实例),ps拥有Student的全部属性,但直接使用时并无PrimaryStudent中比Student多的部分属性。因此,在Main中调用ps.getGrade()时会报错

  System.out.println(ps.getGrade()); // Exception: The method getGrade() is undefined for the type Student

但由于ps实际上是一个PrimaryStudent的实例,我们可以将其向下转型为PrimaryStudent类型来使用getGrade() 方法:

 System.out.println(((PrimaryStudent) ps).getGrade()); //OK

YANGZY1202

#4 Created at ... [Delete] [Delete and Lock User]

完整代码如下:

//Main.java

public class Main {

	public static void main(String[] args) {
		Person p = new Person("小明", 12);
		Student s = new Student("小红", 20, 99);
		// TODO: 定义PrimaryStudent,从Student继承,新增grade字段:
		Student ps = new PrimaryStudent("小军", 9, 100, 5);
		System.out.println(ps.getScore());
		
        //为什么在Main中调用在PrimaryStudent中定义的getGrade()会报错呢??
		System.out.println(ps.getGrade()); 
	}

}
//Person.java

public class Person {

	protected String name;
	protected int age;

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}
//Student.java

public class Student extends Person {

	protected int score;

	public Student(String name, int age, int score) {
		super(name, age);
		this.score = score;
	}

	public int getScore() {
		return score;
	}

	
}


//PrimaryStudent.java
public class PrimaryStudent extends Student{
	
	protected int grade;
	
	public PrimaryStudent(String name, int age, int score, int grade) {
		super(name, age, score);
		this.grade = grade;
	}
	
	public int getGrade() {
		return grade;
	}

}

YANGZY1202

#5 Created at ... [Delete] [Delete and Lock User]

上面的Main.java忘记修改了QAQ:

//Main.java
public class Main {

	public static void main(String[] args) {
		Person p = new Person("小明", 12);
		Student s = new Student("小红", 20, 99);
		// TODO: 定义PrimaryStudent,从Student继承,新增grade字段:
		Student ps = new PrimaryStudent("小军", 9, 100, 5);
		System.out.println(ps.getScore());
		System.out.println(((PrimaryStudent)ps).getGrade());
	}

}


太厉害了,非常感谢题主,这么好的答案为什么要翻到最后一个呢

因为自己也是困扰在了这里,看完题主解答才发现廖老师的代码已经包含了一个向上转型,可能是廖老师故意设计的吧

所以如果更改一下廖老师的代码,不使用转型就可以直接输出方法getGrade(),代码如下

Person p = new Person("小明", 12);

Student s = new Student("小红", 20, 99);

PrimaryStudent ps = new PrimaryStudent("小军", 9, 100, 5);//Student更改为PrimaryStudent,即可不通过转型打印结果

System.out.println(p.name + " " + p.age);

System.out.println(s.name + " " + s.age + " " + s.score);

System.out.println(ps.getgrade());

再提一嘴,由于学到现在,我们已经在不同的代码中多次使用过Person这个类

如果类名重复,即使是在不同的java文件,也会导致Eclipse报错: 

The type Person is already defined

一个简单粗暴的解决办法是更改当前类的类名避免重复,例如把person更改成person2或person+文件名等

ZNnnnnnnnnan

#8 Created at ... [Delete] [Delete and Lock User]

很赞啊!

由于赶进度,一直没有仔细思考,自己把教程和练习弄懂就算了,其实编程还是要多摸索,规则太多!

惭愧!


  • 1

Reply