在继承中调用方法

时间:2016-04-16 07:35:59

标签: java

我遇到了关于对象类型以及可以调用哪种方法的问题。

我只是在测试继承的用法,我定义了两个类:superclass Person和subclass Student。代码如下。

public class Person{

  private String name;
  private int birthday;

  public Person(){

  }

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

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

  public void setBirth(int birthday){
    this.birthday=birthday;
  }

  public String getName(){
    return name;
  }

  public int getBirth(){
    return birthday;
  }
  public String toString(){
    return "Name: "+name+"\n"+"Birthday: "+birthday;
  }

  public void print(Person a){
    System.out.println(toString());
  }
}

学生班:

public class Student extends Person{
  private String major;

  public Student(){}

  public Student(String major,String name,int birthday){
    super(name,birthday);
    this.major = major;

  }

  public void setMajor(String major){
    this.major=major;
  }

  public String getMajor(){
    return major;
  }

  public String toString(){
    return "Name: "+getName()+" BOD: "+getBirth()+" Major: "+getMajor();
  }

  public void print(){
    System.out.println(toString());
  }

}

测试仪。

public class persontest{

  public static void main(String[] args){

    //Part 1

    Person p2 = new Person("p2 Ryan", 19920604);
    p2.print(p2);

//Test 1 p2-->Student
    p2=new Student();// what does it mean??
    p2.print(p2); //which 'toString' should be called??


//1.If p2 is now a Student Why can't invoke Student's print()? (Uncomment 'p2.print()')

//        p2.print();

//2. If p2 isn't a Studnet, why is it able to call Student's toString()? (Uncomment toString in Student)

  }
}

我宣布' toString()'方法和' print()'人和学生班的方法。

作为方法' print()'在Person类中有参数,而在Student类中没有参数,我认为这个方法是重载而不是被覆盖。

'的toString'方法已在Student class中重写。

在第1部分中,我创建了一个对象p2,其中包含名称和生日的初始化,并且输出得到满足(姓名:p2 Ryan生日:19920604)。 )

然后我尝试了#p2 =新学生()',这是什么意思?将p2的类型从Person更改为Student?

然后我做了&#p ;print(p2)'我认为所谓的方法'打印()'在Person类中,但是' toString'已被调用并用作参数?打印输出是(姓名:null BOD:0 Major:null),我认为这表明学生的#String'方法已被调用和处理。并且它可能证明p2现在是一种人物?

然而,当我试图获得p2电话' print()'在Student方法中,出现了错误'类型为Person的方法print(Person)不适用于arguments()',这似乎表示p2仍然是Person,因此无法调用方法' print()'在学生班中定义。

所以我很困惑p2是什么类型的?

3 个答案:

答案 0 :(得分:0)

bootstrap(AppComponent, [
  HTTP_PROVIDERS,
  provide(RequestOptions, {useClass: CustomRequestOptions})
]);

// p2.print();

// 2。如果p2不是Studnet,为什么它能够调用Student's toString()? (在学生中取消注释toString)

} }

答案 1 :(得分:0)

使用Person p2 = new Student(),您已声明了一个类型为Person的新变量,但为其分配了一个学生对象。 变量类型仍然是人,因此您无法直接从学生上调用方法。 要做到这一点,你必须先把它投给学生

((student) p2).print()

这将从学生班级调用print()方法。

但是,如果要覆盖方法,则始终从对象调用方法,因为编译器会检查对象所属类型的运行时间并在此对象上调用方法。这称为动态绑定。

从学生对象中的人访问覆盖方法的唯一方法是使用super调用方法,所以:

super.toString();

但这只能在学生班内完成。

答案 2 :(得分:0)

弱和强类型:表示:

可以看出每个不是基元的变量都具有弱类型和强类型。弱类型用于重载解析,并且编译器可以查看对象具有的接口。但实际调用对象上的方法时会使用强类型。注意:强类型始终与弱类型的直接或间接子类型相同。我们来看看:

A obj = new A();

弱类型和强类型都是A

A obj = new B();

弱类型为A,但强类型为B

编译器使用weak类型来检查对象具有哪个接口(方法集合)。因此,我们只能在Aobj而非B调用方法。所以如果这些类看起来像这样:

class A { }

class B extends A {
    public void bMehtod(){
        ...
    }
}

我们无法在bMethod上致电obj,因为bMethod不属于A界面。

为了覆盖,当实际调用方法时使用强类型。就像JVM从强类型开始一样,向上移动继承链,直到找到被调用方法的出现。所以如果我们的课程看起来像这样:

class A {
     public String toString() {
        return "A";
     }
}

class B extends A {
    public String toString() {
         return "B";
    }
}

我们创建一个对象并调用toString

A obj = new B();
System.out.println(obj); // this will call 'obj.toString()'

JVM将从强类型(B)开始,并查找toString方法。如果它找不到任何东西,它将向上移动继承链。但是,B会覆盖toString,因此B toString会被调用。当添加第三个类时,这变得更加明显:

class C extends B { }

如果我们现在创建一个对象并调用toString

A obj = new C();
System.out.println(obj);

JVM将从C开始寻找toString方法,它找不到任何方法并向上移动到B,在那里找到toString方法。因此,B toString方法将被调用。

这与您的问题有什么关系:

就像其他变量一样,this具有弱而强的类型。弱类型是写入this关键字的类。强类型是创建对象的实际类型。

print方法中:

public void print(Person a){
    System.out.println(toString());
}

toString()被隐式翻译为this.toString()this的弱类型是Person,因此可以在其上调用toString,它是Person的一部分&#39}。接口。但强类型是您实际用于创建对象的类型:

p2 = new Student();

this的强类型为Student,因此在查找Student方法时,JVM将从toString开始,并在Student中找到它}。因此调用Student' toString方法。

就像我说这只是一种表示,它实现的实际方式可能因JVM而异。但它仍然会表现得一样。

另请参阅Live Demo