继承和多态(一)

        什么是继承?继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了 由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。被继承的是父类,也叫超类,基类,继承的是子类,派生类。

class Person{//父类
    public String name;
    public int age;
}
class Student extends Person{//子类
    public int grades;
}
Java 中如果要表示类之间的继承关系,需要借助 extends 关键字。
注意:
1. 子类会将父类中的成员变量或者成员方法继承到子类中了
2. 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
3.子类与父类之间必须要有某种联系,不能因为父类的成员变量中有子类所需要的就继承,如:
class Animal{
    public String name;
    public int age;
}
class Student extends Animal{
    public int grades;
}

虽然语法可以通过,但逻辑上不行,怎么可以将风马牛不相及的东西放在一起呢,这会增加代码的阅读难度。

        如果子类要访问父类的成员,要如何访问呢?若要访问的父类成员,在子类中没有相同的,则与访问子类成员的方法一样,可以通过对象名来使用,但不能通过this来访问父类成员,若子类中有相同的,这要通过关键字super访问。

class Student extends Person{//子类
    public String name;
    public int grades;
    public void eat(){
        System.out.println(super.name + "年龄为" + super.age + "正在吃饭");
    }
}

注意:

在子类方法中 或者 通过子类对象访问成员时
如果访问的成员变量子类中有,优先访问自己的成员变量。
如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找
通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同 ( 重载 ) ,根据调用 方法适传递的参数选择合适的方法访问,如果没有则报错;
super关键字
1. 只能在非静态方法中使用
2. 在子类方法中,访问父类的成员变量和方法
        子类的构造方法
在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法,因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子, 肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整, 然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整
注意:
1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的 super() 调用,即调用基类构 造方法
2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的 父类构造方法调用,否则编译失败。
3. 在子类构造方法中, super(...) 调用父类构造时,必须是子类构造函数中第一条语句。
4. super(...) 只能在子类构造方法中出现一次,并且不能和 this 同时出现
class Person{//父类
    public String name;
    public int age;
}
class Student extends Person{//子类
    public int grades;
    public Student(int grades){
        this.super();//this和super同时出现,报错
        super();
        this.grades = grades;
    }
}

        那么子类和父类的的初始化顺序是什么呢?谁先初始化呢?如果里面包含了静态代码块和实例代码块呢?

1 、父类静态代码块优先于子类静态代码块执行,且是最早执行
2 、父类实例代码块和父类构造方法紧接着执行
3 、子类的实例代码块和子类构造方法紧接着再执行
4 、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行
class Person{
    public String name;
    public int age;

    static {
        System.out.println("父类静态代码块");
    }

    {
        System.out.println("父类实例代码块");
    }

    public Person(){
        System.out.println("父类构造方法");
    }

}
class Student extends Person{
    static {
        System.out.println("子类静态代码块");
    }

    {
        System.out.println("子类实例代码块");
    }

    public Student(){
        System.out.println("子类构造方法");
    }
}

打印结果为:

父类静态代码块
子类静态代码块
父类实例代码块
父类构造方法
子类实例代码块
子类构造方法

继承就先到此结束了。

你可能感兴趣的:(java,开发语言)