栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java中的继承与多态(继承篇)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java中的继承与多态(继承篇)

写在前面:
博主主页:戳一戳,欢迎大佬指点!
博主秋秋:QQ:1477649017 欢迎志同道合的朋友一起加油喔
目标梦想:进大厂,立志成为一个牛掰的Java程序猿,虽然现在还是一个小菜鸟嘿嘿
-----------------------------谢谢你这么帅气美丽还给我点赞!比个心-----------------------------


继承和多态
  • 一,继承
    • 1.1,为什么要继承
    • 1.2,继承的语法
    • 1.3,父类成员的访问
      • 1.3.1,子类访问父类中的成员变量
        • 1,子类与父类不存在同名成员变量
        • 2,子类与父类存在同名的成员变量
      • 1.3.1,子类访问父类中的成员方法
        • 1,子类父类不存在同名方法
        • 2,子类和父类存在同名的方法
    • 1.4,super关键字
    • 1.5,子类的构造方法
    • 1.6,super与this
    • 1.7,初始化问题
    • 1.8,protected关键字
    • 1.9,继承的方式
    • 1.10,final关键字
    • 1.11,继承与组合


一,继承 1.1,为什么要继承

首先,我们已猫和狗两个类进行下对比,我们就可以发现,它们两个类有共同的地方,那既然是公有的,为什么不进行抽离呢?这样就不用写两遍了,这其实就是继承的思想。

class Animal{//动物类
    public String name;
    public int age;
}
class Dog extends Animal{
    public void bark(){
        System.out.println(this.name + "正在汪汪汪");
    }
}
class Cat extends Animal{
    public void miao(){
        System.out.println(this.name + "正在miaomiao");
    }
}

当我们进行共性的抽取之后,就得到了如上的代码,其中extends表示是继承的关系。

总结而言,继承的作用就是为了实现共性的抽离,进而实现代码的复用


1.2,继承的语法
访问修饰符 class 子类名 extends 父类名{}
class Animal{
    public String name;
    public int age;
}
class Dog extends Animal{
    public String color;
    public void bark(){
        System.out.println(this.name + "正在汪汪汪");
    }
}

看这段代码,Dog类继承了Animal类,那可能有同学要问了,现在如果说new一个dog对象,它的内存图是怎么样的呢?

注意:

1,子类会将父类中的成员变量或者成员方法继承到子类中了

2,子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了


1.3,父类成员的访问 1.3.1,子类访问父类中的成员变量 1,子类与父类不存在同名成员变量
class Father{
    public int date1 = 1;
    public int date2 = 2;
}
class Son extends Father{
    public int date3 = 3;
    public int date4 = 4;

    public void func(){
        System.out.println(this.date1);
        System.out.println(this.date2);
        System.out.println(this.date3);
        System.out.println(this.date4);
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Son son = new Son();
        son.func();
    }
}

程序运行截图:

内存布局:

当我们的子类继承父类后,子类的对象里面不仅仅存储着自己特有的成员属性,也有从父类那里继承过来的成员属性,所以通过子类的对象引用this都是可以访问到的。


2,子类与父类存在同名的成员变量
class Father{
    public int date1 = 111;
    public int date2 = 2;
}
class Son extends Father{
    public int date1 = 1;
    public int date3 = 3;
    public int date4 = 4;

    public void func(){
        System.out.println(this.date1);
        System.out.println("父类同名成员" + super.date1);
        System.out.println(this.date2);
        System.out.println(this.date3);
        System.out.println(this.date4);
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Son son = new Son();
        son.func();
    }
}

程序运行截图:

内存布局:

当我们存在同名的成员变量时,你通过子类对象的引用this去访问的话,它肯定默认是优先访问子类的同名成员变量,如果我们想访问父类的同名成员变量的话,要用 super.变量名 去访问才行,,super代表的是从父类继承过来的属性的引用,有的书上也说super是父类的引用,但是这种说法其实是不准确的


总结:

当我们在子类方法或者通过子类对象进行访问成员变量的时候,遵循就近原则,优先访问子类自己的,如果没有就去父类中找,父类中也没有那就编译报错。针对同名的成员变量,this只能访问子类自己的,要访问父类的同名成员变量,用super去访问。


1.3.1,子类访问父类中的成员方法 1,子类父类不存在同名方法
class Father{
    public void fatherMethod(){
        System.out.println("父类方法");
    }
}
class Son extends Father{
    public void sonMethod(){
        System.out.println("子类方法");
    }
    public void func(){
        this.fatherMethod();
        this.sonMethod();
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Son son = new Son();
        son.func();
    }
}

程序运行截图:

既然子类是继承了父类的,所以通过子类当前对象的引用this就可以都调用到。


2,子类和父类存在同名的方法
class Father{
    public void MethodA(int val){
        System.out.println("父类方法MethodA " + val);
    }
    public void MethodB(){
        System.out.println("父类方法MethodB");
    }
}
class Son extends Father{
    public void MethodA(){
        System.out.println("子类方法MethodA");
    }
    public void MethodB(){
        System.out.println("子类方法MethodB");
    }
    public void func(){
        this.MethodA(10);
        this.MethodA();
        this.MethodB();
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Son son = new Son();
        son.func();
    }

程序运行截图:

当子类和父类存在同名的成员方法的时候,依然是就近原则,优先访问子类的,注意,对于同名的方法,是有可能发生重载的,重载不一定是发生在同一个类里面,比如这里的MethodA父类子类就发生了重载,对于这种的话,虽然是同名,我们通过this依然是能够精确访问到的,但是如果同名方法发生的是重写的话(名字,返回值,参数列表都一样),那这个时候就只会优先访问子类自己的方法了,要访问父类的只能用关键字super。


1.4,super关键字

super关键字的作用:

1,super.成员名 访问父类的成员

2,super.方法名 访问父类的方法

3,super() 调用父类的构造方法


注意:和this一样,只能在非静态方法里面使用。


1.5,子类的构造方法
class Animal{
    public String name;
    public int age;

    public Animal(String name,int age){//父类构造方法
        this.name = name;
        this.age = age;
    }
}
class Dog extends Animal{
    public String color;
    public Dog(String name,int age,String color){//子类构造方法
        super(name,age);
        this.color = color;
    }
    public void bark(){
        System.out.println(this.name + " 正在汪汪汪");
    }

}

public class TestDemo {
    public static void main(String[] args) {
        Dog dog = new Dog("大黄",4,"黄色");
        dog.bark();
    }
}

要实例化出子类对象,那首先肯定得有父类对象,先有父才有子,所以在子类的构造方法里面我们得显式的调用父类的构造方法,来对继承过来的属性进行初始化。


注意:

1,如果说父类子类都没有显式的写构造方法,这种情况下,父类子类编译器都会默认提供无参构造方法,并且子类的构造方法默认是给你调用了父类的构造方法的。(在无参构造的情况下,子类父类的构造方法都不写,或者写其中一个都没有问题,因为编译器会我们提供,并且调用父类构造方法)
2,如果说父类的构造方法是有参的,那么这个时候子类的构造方法必须自己写,并且调用父类的这个有参构造。
3,在子类的构造方法中,super()调用父类构造方法,只能放在子类构造方法的第一行。
4,super()在子类构造方法中只出现一次,并且不能与this()同时出现(因为两个都要争着放在第一行,矛盾了)。并且如果父类是无参构造的情况下,super()是隐藏存在的,所以这个时候注意别说没看到super(),然后你去用了this()也是错的。


1.6,super与this


1.7,初始化问题

在前面的类里面,我们就探讨过在一个类里面的初始化顺序的问题,那现在涉及到继承了,它的初始化顺序又是怎样的呢?

class Animal{
    public String name;
    public int age;
    static{
        System.out.println("Animal的静态代码块");
    }
    {
        System.out.println("Animal的实例代码块");
    }
    public Animal(){
        System.out.println("Animal的构造方法");
    }
}
class Dog extends Animal{
    public String color;
    static{
        System.out.println("Dog的静态代码块");
    }
    {
        System.out.println("Dog的实例代码块");
    }
    public Dog(){
        System.out.println("Dog的构造方法");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println("===========");
        Dog dog1 = new Dog();
    }
}

程序运行截图:

对于继承当中的初始化顺序,总结来说,就是由父及子,静态先行,并且静态内容只初始化一次。(我们讨论的顺序针对的是成员,代码块以及构造方法的执行顺序,方法都是要调用才会执行)


1.8,protected关键字

对于protected修饰符,对于在同一个包里面,是没有任何限制的,不管是不是在一个类,但是涉及到继承上,在不同包上,必须是子类才可以访问到。

这里主要说下不同包中的子类,在子类中需要利用super才能访问。

//包demo1下
package demo1;
public class Test {
    protected int a;

    public static void main(String[] args) {

    }
}

//包demo2下
package demo2;
import demo1.Test;
public class Demo extends Test {
    public void func(){
        System.out.println(super.a);
    }
    public static void main(String[] args) {
        //Test test = new Test();
//        System.out.println(test.a);访问方式是错的
        Demo dmo = new Demo();
        dmo.func();
    }
}


1.9,继承的方式


1.10,final关键字

1,修饰变量,表示这是一个常量,不能被修改

final int a = 10;

2,修饰类,表示该类不能被继承

final class B extends A{};//类B不能在被继承

3,修饰方法,表示该方法不能被重写。


1.11,继承与组合

继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物

组合表示对象之间是has-a的关系,比如:汽车与其各个零部件之间,汽车是由它们组成

class Engine{//引擎类
    
}
class Tire{//轮胎类
    
}
...
class Car{//车类
    public Engine engine;
    public Tire tire;
}

和继承一样,组合也是能够实现代码的复用的,因为对于组合而言,只是将某一个类的实例作为了另外一个类的字段。


最后,今天的文章分享比较简单,就到这了,如果大家觉得还不错的话,还请帮忙点点赞咯,十分感谢!殺殺殺

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/884889.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号