继承进一步使用,以及super关键字

目标:

1)掌握子类对象实例化过程

2)掌握方法覆盖概念和实现。

3)掌握super关键字的作用。

一,子类对象实例化过程

子类对象在实例化之前,必须先调用父类中的构造方法,再调用子类中的构造方法。

class Person{                    // 定义Person类
    private String name ;        // 定义name属性
    private int age ;            // 定义age属性
    public Person(){
        System.out.println("父类Person中的构造。") ;
    }
    public void setName(String name){
        this.name = name;    
    }
    public void setAge(int age){
        this.age = age ;
    }
    public String getName(){
        return this.name ;
    }
    public int getAge(){
        return this.age ;
    }
};
class Student extends Person{                    // 定义Student类
    private String school ;        // 定义school属性
    public Student(){
        super() ;    // 默认隐藏
        System.out.println("子类Student中的构造。") ;
    }
    public void setSchool(String school){
        this.school = school ;
    }
    public String getSchool(){
        return this.school ;
    }

};
public class InstanceDemo{
    public static void main(String arsg[]){
        Student stu = new Student()    ;// 实例化子类对象
        stu.setName("张三") ;    // 此方法在Student类中没有明确定义
        stu.setAge(30) ;
        stu.setSchool("清华大学") ;
        System.out.println("姓名:" + stu.getName() + ",年龄:" + stu.getAge() + ",学校:" + stu.getSchool() ) ;
    }
};

运行结果:

父类Person中的构造。
子类Student中的构造。
姓名:张三,年龄:30,学校:清华大学

在生活中也很好理解,没有父亲就没有孩子。

实际上,对于子类的构造方法中,隐含了一个“super()”的语句。有时候,也将父类称为超类,所以调用父类构造方法,用super()

super关键字必须写在构造方法的首行。

二,方法的复写

方法覆写就是指:子类中定义了与父类中同名的方法。

1)但是在方法覆写时必须考虑访问权限,即:被子类覆写的方法,不能拥有比父类更严格的访问权限。

2)所以,如果在父类中使用public定义的方法,子类的访问权限必须是public,否则无法编译。

3)private<default<public。

class Person{        // 定义父类
    void print(){    // 默认的访问权限
        System.out.println("Person --> void print()。") ;
    }
};
class Student extends Person{    // 定义继承关系
    public void print(){
        System.out.println("Student --> void print()。") ;
    }
};
public class OverrideDemo01{
    public static void main(String args[]){
        Student s = new Student() ;
        s.print() ;
    }
};
运行结果:
Student-->void print()。

访问权限:

private:最小的访问权限。

default:什么都不写,例如:string name;

public:最大的访问权限。

以下是访问权限出问题的错误操作。

package methoud;
class Person{        // 定义父类
    public void print(){    // public的访问权限
        System.out.println("Person --> void print()。") ;
    }
};
class Student extends Person{    // 定义继承关系
     void print(){    // 错误的,降低了访问权限
        System.out.println("Student --> void print()。") ;
    }
};
public class ThisDemo06{
    public static void main(String args[]){
        Student s = new Student() ;
        s.print() ;
    }
};

由于子类的访问权限default小于public,所以编译通过不了。

从之前正确操作可以看出,如果子类将父类的方法覆写了,调用的时候,肯定是调用被覆写过的方法,那么如果非要调用父类的方法。

通过“super”关键字可以完成功能,super关键字可以从子类访问父类的内容。

如果要访问被覆写过的方法的方法:super.方法();

例如:

class Person{        // 定义父类
    void print(){    // 默认的访问权限
        System.out.println("Person --> void print()。") ;
    }
};
class Student extends Person{    // 定义继承关系
    public void print(){
        super.print() ;    // 访问父类中被子类覆写过的方法
        System.out.println("Student --> void print()。") ;
    }
};
public class OverrideDemo03{
    public static void main(String args[]){
        Student s = new Student() ;
        s.print() ;
    }
};
运行结果:
Person --> void print()。

Student --> void print()。

如果要使用“super”不一定非要在方法覆写之后使用,也可以明确表示某个方法是从父类中继承而来的。

使用super只是更加明确的说直接从父类中寻找,就不从子类找了。因为没有super调用方法,首先从子类寻找,如果子类没有才到父类寻找。

例如:如果上面那个例子中super.print()把super去掉,就会造成无限期循环递归,自己调用自己

三,问题:

如果父类中使用private关键字声明一个方法,那么在子类中使用default权限算是扩大权限,覆写吗?

答案是:NO,不算覆写。

正常覆写:

class Person{        // 定义父类
    void print(){    // 默认的访问权限
        System.out.println("Person --> void print()。") ;
    }
    public void fun(){    // 定义一个fun方法
        this.print() ;    // 调用print()方法
    }
};
class Student extends Person{    // 定义继承关系
    void print(){    // 覆写父类中的方法
        System.out.println("Student --> void print()。") ;
    }
};
public class OverrideDemo04{
    public static void main(String args[]){
        Student s = new Student() ;
        s.fun() ;
    }
};
运行结果:

  Student --> void print()。

这里因为正常覆写,所以直接调用了子类中的覆写方法。

错误的覆写:

package methoud;
class Person{        // 定义父类
    private void print(){    // private的访问权限
        System.out.println("Person --> void print()。") ;
    }
    public void fun(){    // 定义一个fun方法
        this.print() ;    // 调用print()方法
    }
};
class Student extends Person{    // 定义继承关系
    void print(){    // 覆写父类中的方法
        System.out.println("Student --> void print()。") ;
    }
};
public class ThisDemo06{
    public static void main(String args[]){
        Student s = new Student() ;
        s.fun() ;
    }
};
运行结果:
Person-->void print();

可见,这里并没有调用子类中的“覆写”方法,而是调用父类中默认的方法。说明这里并没有达到覆写的作用,子类中的方法其实是另外定义了一个方法。

这点需要注意!

四,属性的覆盖。

覆盖,就是指子类中声明了父类中同名的属性。

class Person{        // 定义父类
    public String info = "MLDN" ;    // 定义一个公共属性
};
class Student extends Person{    // 定义继承关系
    public String info = "LXH" ;    // 定义了一个与父类中属性名称一致的属性
    void print(){    // 覆写父类中的方法
        System.out.println("父类中的属性:" + super.info) ;
        System.out.println("子类中的属性:" + this.info) ;
    }
};
public class OverrideDemo05{
    public static void main(String args[]){
        Student s = new Student() ;
        s.print() ;
    }
};

可见,要使用被覆盖的父类中的属性,需要使用super关键字。

五,方法覆盖与重载的区别

六,super关键字

super表示的是从子类调用父类中的指定操作。例如调用属性,方法,构造等等。

因为在子类实例化的时候,会默认调用父类中的无参数构造方法(“super()”)。如果想调用有参构造方法,则必须在子类中明确声明。

class Person{                    // 定义Person类
    private String name ;        // 定义name属性
    private int age ;            // 定义age属性
    public Person(String name,int age){
        this.setName(name) ;
        this.setAge(age) ;
    }
    public void setName(String name){
        this.name = name;    
    }
    public void setAge(int age){
        this.age = age ;
    }
    public String getName(){
        return this.name ;
    }
    public int getAge(){
        return this.age ;
    }
    public String getInfo(){
        return "姓名:" + this.getName() + ";年龄:" + this.getAge() ;
    }
};
class Student extends Person{                    // 定义Student类
    private String school ;        // 定义school属性
    public Student(String name,int age,String school){
        super(name,age) ;    // 明确调用父类中有两个参数的构造
        this.school = school ;
    }
    public void setSchool(String school){
        this.school = school ;
    }
    public String getSchool(){
        return this.school ;
    }
    public String getInfo(){
        return super.getInfo() + ";学校:" + this.getSchool() ;
    } 

};
public class SuperDemo01{
    public static void main(String arsg[]){
        Student stu = new Student("张三",30,"清华大学")    ;// 实例化子类对象
        System.out.println(stu.getInfo()) ;
    }
};

不管任何时候,子类实例化的时候,永远要先去调用父类中的构造方法,默认调用的是无参构造方法。

1)对于this和super本身都可以调用构造方法,而且调用的时候都必须放在构造方法的首行。所以这两个方法肯定不能同时出现。

原文地址:https://www.cnblogs.com/alsf/p/5525298.html