带你深入理解面向对象三大特性 - 继承,多态

目录

前言:

继承

示例

子类中访问父类成员变量

变量名字不同

变量名字相同

子类中访问父类成员方法

方法名字不同

方法名字相同

super关键字

子类构造方法

super和this

再谈初始化

继承方式:

单继承

多继承

不同类继承同一类

 final关键字

final修饰成员变量

final修饰成员方法

final修饰类

继承与组合

多态

多态的条件

重写

方法重写的规则

示例

静态绑定

动态绑定

向上转型

向下转型

 小结:


前言:

   为了实现代码的复用,让代码看起来不在冗余,将两个类相同的部分提取出来,用子类去继承父类就可以达到这样的效果。

    多态字面意思就是多种状态,这是一种思想,在Java中理解:一个引用调用同一个方法,产生的行为不一样。

继承:

😯被继承的类称为,父类、基类或者超类。继承的类称为子类或者派生类。

示例

class Person {
    private int age;
    private String name;
    public void eat() {
        System.out.println(name + "在吃饭");
    }
    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
class Student1 extends Person {
    boolean sleep;
    public void fun() {
        System.out.println("在睡觉");
    }
}
class Student2 extends Person {
    public void fun() {
        System.out.println("在学习");
    }
}
public class Test7 {
    public static void main(String[] args) {
        Student1 stu1 = new Student1();
        stu1.setAge(21);
        stu1.setName("www");
        System.out.println(stu1.getName() + stu1.getAge());
    }
}

🐵继承使用关键子extends,继承之后子类可以复用父类的成员,但必须要保证子类中有特有的属性或者行为,否则就没有必要去继承了。

子类中访问父类成员变量:

变量名字不同

🎈在子类中就正常访问父类中的成员。

变量名字相同

🎈就近原则,优先访问子类中的成员变量,如果想要访问父类中的成员变量,需使用super关键字(后续介绍)。

子类中访问父类成员方法:

方法名字不同

😯和访问变量原则一样,直接访问就行。

方法名字相同

😯就近原则,优先访问子类中的成员方法,如果想要访问父类中的成员方法,也需super关键字。与变量的访问规则对比着去理解。

super关键字

😊super的存在,解决了在子类中访问父类中相同的成员变量和方法。

class Person3 {
    int a;
    int b;
    public void fun() {
        System.out.println("aaaa");
    }
}
class Student3 extends Person3{
    int a;
    int b;
    int c;
    public void fun() {
        System.out.println("bbbb");
    }
    public void func() {
        a = 0;
        super.a = 10;
        super.b = 20;
        super.fun();
        fun();
        System.out.println(super.a);
        System.out.println(a);
    }
}
public class Test8 {
    public static void main(String[] args) {
        Student3 stu = new Student3();
        stu.func();
    }
}

🎉 可以清楚的看见通过super访问到了父类中的成员变量和方法。

注意:super只能在非静态方法中使用,因为静态方法是属于类的,它不属于某一个对象。

子类构造方法

🪖首先不同类的构造方法肯定在不同类中,虽然子类继承了父类,但在用子类实例化对象时需要调用父类的构造方法,完成父类中成员的构造,接下来调用子类的构造方法,完成子类成员的构造。父类构造方法需先调用,然后再调用子类的构造方法。这是用子类实例化对象的必要条件

示例

class Person8{
    int age;
    String name;
    public Person8(String name) {
        age = 21;
        System.out.println(name + this.age);
    }
}
class Student8 extends Person8{
    boolean sleep;
    public Student8() {
        //必须在第一句
        super("www");
        sleep = false;
        System.out.println(sleep);
    }
}
public class Test9 {
    public static void main(String[] args) {
        Student8 stu = new Student8();

    }
}

 💎可以清楚看见先调用父类构造方法然后调用子类构造方法

注意:

🎄如果父类定义了无参构造方法,或者没有定义构造方法,则在子类中构造方法第一句默认super()调用了父类构造方法。

🎄子类调用父类构造方法必须在子类构造方法中第一句

🎄super和this不能同时存在,因为this调用构造方法也得放在第一句。

super和this

相同点:

🧢都是关键字

🧢只能在非静态方法中使用,访问非静态成员变量或者方法。

🧢构造方法调用时只能在第一句,且不能同时存在

不同点:

🎉this是当前对象的引用,super可以理解为是子类中所继承父类对象的引用。

🎉在非静态方法中,this用来访问本类的成员和方法,super用来访问父类的成员和方法。

🎉在构造方法中,this()调用本类构造方法,super()调用父类构造方法。

🎉子类构造方法中一定存在super(),程序员没有写编译器也会增加,但是this()不写则没有。

再谈初始化

😆继承关系下,静态代码块,示实例代码块,构造方法的执行顺序?

class Person8{
    int age;
    String name;
    static {
        System.out.println("Person8的静态代码块");
    }
    {
        System.out.println("person8的实例代码块");
    }
    public Person8() {

        System.out.println("Person8的构造方法");
    }
}
class Student8 extends Person8{
    boolean sleep;
    static {
        System.out.println("Student8的静态代码块");
    }
    {
        System.out.println("Student8的实例代码块");
    }
    public Student8() {
        super();
        System.out.println("Student8的构造代码块");
    }
}
public class Test9 {
    public static void main(String[] args) {
        Student8 stu = new Student8();
        System.out.println("------------------");
        Student8 stu2 = new Student8();
    }
}

 🤨首先执行父类静态代码块,然后执行子类静态代码块,接下来执行父类实例代码块和构造方法,再然后执行子类实例代码块和构造方法。父类和子类静态代码块执行一次,它们在类的加载时就执行了。实例代码块和构造方法只要实例化对象就会执行。

继承方式:

单继承

B ----> A      B类继承A类

多继承

B ----> A ----> C  A类继承C类,B类继承A类

不同类继承同一类

B ----> A   C ----> A  B类继承A类,C类也继承A类。

🐵我们不希望继承层次太过于复杂,继承层次一般不能超过三层

注意:Java中不支持多继承,一个类同时继承多个类。

final关键字:

🤨final可以用来修饰成员变量,成员方法以及类。。

final修饰成员变量

🤨该变量为常量,不可以被修改,存储在JVM中的方法区

final修饰成员方法

🤨该方法不能被重写。(多态中详解)

final修饰类

🤨该类不能被继承。

继承与组合

🪖继承是一种联结类与类的层次模型,子类继承父类,可以增加自己的功能,是一种is - a的关系。

🪖组合是在新类中产生现有类的对象,因此新的类是由现有类的对象所组成,可以复用现有类中的属性和方法。是一种has - a的关系。

示例

lass Person9 {
    int age;
    String name;
    public void fun() {
        name = "www";
        System.out.println(name + "在学习");
    }
}
class Student9 {
    Person9 stu = new Person9();
    Person9[] stu2 = new Person9[10];
    public Student9(int age, String name) {
        stu.age = age;
        stu.name = name;
    }
    public void fun() {
        System.out.println(stu.name + stu.age);
        stu.fun();
    }
}
public class Test10 {
    public static void main(String[] args) {
        Student9 stu = new Student9(21, "www");
        stu.fun();
    }
}

多态 

😉多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。(可能不是很容易理解,下面会体现这种思想)

多态的条件(缺一不可)

😊必须在继承关系下。

😊子类必须要对父类的方法进行重写

😊通过父类的引用调用重写的方法。

重写

😆这个是建立在继承关系上的,子类对继承父类的一些方法不是很满意,自己再去写一遍这个方法,这个就是实现多态的首要条件。

😆重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。核心代码重写

方法重写的规则

😯形参列表不能改变,形参的顺序,个数,类型都不能改变。

😯返回值需相同,或者具有父子关系。

😯方法权限只能大于或者等于被重写的方法。

😯父类被static、private或者构造方法都不能重写。

注意:

 🎈方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

 🎈父类被private修饰的方法或者属性虽然被继承了,但是子类中是无法访问的。

示例

class Person6 {
    int age;
    String name;
    public void eat() {
        name = "www";
        System.out.println(name + "吃米饭");
    }
}
class Student6 extends Person6{
    boolean sleep;
    public void eat() {
        name = "w";
        System.out.println(name + "吃鱼");
    }
}
class Student7 extends Person6 {
    public void eat() {
        name = "ww";
        System.out.println(name + "吃肉");
    }
}
public class Test11 {
    public static void fun(Person6 stu) {
        stu.eat();
    }
    public static void main(String[] args) {
        Student6 stu1 = new Student6();
        Student7 stu2 = new Student7();
        fun(stu1);
        fun(stu2);

    }
}

 😯多态的体现:同一个引用(对象不同),调用同一个方法,产生的行为却不同

静态绑定

🐵也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表方法重载

动态绑定

🐵也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。(编译看左边,运行看右边)

向上转型

😉概念:创建一个子类对象,被父类所引用。

​
class W2 {
    int a;
    public void fun() {
        a = 10;
        System.out.println(a);
    }
}
class W3 extends W2 {
    int b;
    public void fun() {
        System.out.println("aaaaa");
    }
}
public class Test12 {
    public static void main(String[] args) {
        //向上转型
        W2 stu = new W3();
        stu.fun();
        //向下转型
        //确保stu引用了W3这个对象
        if(stu instanceof W3) {
            W3 stu2 = (W3) stu;
            //访问子类中特有成员
            System.out.println(stu2.b);
        }
    }
}

注意:向上转型,最后运行时原理就是动态绑定,让代码更加灵活。

向下转型

代码(W2父类    W3子类)

    W2 stu = new W3();

    W3 stu2 = (W3) stu;(向下转型)

🤨向上转型,只能访问子类中父类被子类重写的方法、被继承父类中的属性和父类中没有被子类重写的方法。无法访问子类中特有的方法或者属性。

🤨向下转型,可以访问子类中特有的方法或者属性。

注意:向下转型不是很安全,需保证其可以正常还原。

 小结:

🐵理解是学习首当其冲进行的,需大量练习才能提高我们的代码能力,坚持下去会有不一样的收获。

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小太空人w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值