面向对象——继承,多态

面向对象——继承

java中的继承,父类的成员,子类可以继承

要实现父子继承,使用extends实现

继承可以提高代码的复用性和维护性

但是也有不利性:

让类与类之间产生了父子关系,增加了耦合性。

耦合:完成一个功能,要去依赖别的类。

如果我们的软件大量的增加了耦合性,我们软件在后期的维护会很麻烦,

package demo2;

public class an {
    String name;
    int age;
    public void sleep(){
        System.out.println("睡觉");
    }
    public void eat(){
        System.out.println("吃饭");
    }
}
//父类
public class dog extends an{
    public void lookdoor(){
        System.out.println("看门");
    }
}
//子类
public class cat extends an{
    public void mouse(){
        System.out.println("抓老鼠");
    }
}
//子类
public class text {
    public static void main(String[] args) {
        cat cat = new cat();
        cat.age=2;
        cat.name="刘";
        System.out.println(cat.age);
        System.out.println(cat.name);
        cat.mouse();//对父类的调用
        cat.eat();
        cat.sleep();
        dog dog = new dog();
        dog.age=1;
        dog.name="吴";
        System.out.println(dog.age);
        System.out.println(dog.name);
        dog.lookdoor();//对父类的调用
        dog.eat();
        dog.sleep();
    }
}
//输出

继承的语法特点:

只支持单继承,一个类,只有一个父类,一个父类,可以有多个子类(联系生活)

也支持多层继承(爷—父—孙)

public class demo {
        public static void main(String[] args) {
            Grandson grandson = new Grandson();
            System.out.println(grandson.g);
            System.out.println(grandson.f);
            grandson.show();
            grandson.fuShow();
        }
    }
    class Grandfather {
        String g = "ggggg";
        public void show() {
            System.out.println("爷爷类中的show方法");
        }
    }
    class Father extends Grandfather {
        String f = "ffff";
        public void fuShow() {
            System.out.println("父亲的show方法");
        }
    }
    class Grandson extends Father {
    }
    class Grandson2 extends Father {
    }

注意:

1.父类的私有成员,子类不能继承

2.构造方法不参与继承

3.不要为了继承而继承

父子关系中的变量访问

public class demo{
public static void main(String[] args) {
        Son son = new Son();
        son.show(num:20);
        }
        }
class Father {
    int num = 200;
}
class Son extends Father {
    int num = 600;

    public void show(int num) {
        System.out.println(num); //20
        System.out.println(this.num); //600
        System.out.println(super.num);//200
    }
}

变量访问的就近原则:当访问一个变量时,先在方法的局部范围找,找到使用,局部没找到,去本类成员范围找,找到使用,如果本类没找到,去父类找,找到使用,如果找不到,报错。

关键字 super

表示的是父类的空间标识,我们可以使用super关键字去访问父类数据。

super 和 this。

如果访问父类成员变量

super.成员变量名

如果访问本类的成员变量

this.成员变量名

如果访问父类的成员方法

super.成员方法名

本类的成员方法

this.成员方法名

父类的构造方法

super()

本类的构造方法

super();
package demo2;
public class demo{
        public static void main(String[] args) {
            Son son = new Son();
            son.test();
        }
    }
    class Father {
        int fuNum = 200;
        int f = 600;
        public void fuShow() {
            System.out.println("父类的show方法");
        }
    }
    class Son extends Father {
        int num = 20;
        int f = 9000;
        public void ziShow() {
            System.out.println("子类的show方法");
        }
        public void test() {
            System.out.println(super.fuNum);//200
            System.out.println(super.f);//600
            System.out.println(this.fuNum);//20
            System.out.println(this.f); //9000
            System.out.println("========================");
            super.fuShow();
            this.fuShow();
            this.ziShow();
        }
    }

当我去创建子类对象时,为什么会先去调用父类的构造方法

因为:有了继承关系后,当我们初始化子的时候,子类要继承父类的数据,甚至还要去使用父类的数据,这时,我们先会完成父类的初始化。

在每个类的构造方法中的第一行有一行默认的super()这行代码去调用父类的空参构造

那么父类的父类呢?

在java中有一个顶层的父类 object,所有的类,都是直接或间接的继承它。

public class MyTest extends Object{
    public static void main(String[] args) {
        Zi zi = new Zi();
    }
}
class Fu extends Object{
    int fuNum=100;
    public Fu() {
        super();
        System.out.println("父类的构造方法调用了");
    }
}
class Zi extends Fu{
    int ziNum=200;
    public Zi() {
        super();
        System.out.println("子类的构造方法调用了");
    }
}

那么,如果父类没有空参构造呢?

1.给父类构造空参

2.想办法调用父类的有参构造

package demo2;
public class demo {
    public static void main(String[] args) {
                Zi zi = new Zi();
                Zi zi1 = new Zi(20);
            }
        }
        class Fu extends Object{
            public Fu(int num) {
                super();
                System.out.println("父类的有参构造");
            }
        }
        class Zi extends Fu{
            public Zi() {
                super(10); //调用父类的有参构造
                System.out.println("子类 构造执行了");
            }
            public Zi(int num){
                this(); //间接的完成父类数句的初始化,调用本类空参构造
                System.out.println("子类有参构造执行了");
            }
        }

方法重写

当子类和父类出现了一模一样的方法的时候(方法名,参数 返回值一样)就会发生方法覆盖现象,称之为方法重写。子类方法会覆盖父类方法。

为什么要有方法重写:子类对父类的功能实现,并不是很满意,子类想要改写掉父类的功能,或者说想要扩展父类的功能。那么子类都可以使用方法重写来完成。

package demo2;

public class fu {
    public void fushow(){
        System.out.println("fu类对show的调用");
    }
    public void eat(){
        System.out.println("fu的eat功能实现");
    }
}

package demo2;

public class zi extends fu{
    public void zishow(){
        System.out.println("zishow的重写");
    }
    public void eat(){
        System.out.println("zi对eat的重写");
    }
}

package demo2;

public class txet1 {
    public static void main(String[] args) {
        zi zi = new zi();
        zi.fushow();
        zi.eat();
        zi.zishow();
    }
}

重写的注意事项:

1.父类私有的方法,子类不能重写。

2.子类在重写父类方法时,方法前面的修饰符,不能比父类的低,可以等于和高,最好一样

3.静态方法,不参与重写

案例:

public class MyTest {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.fuStatic();
        Zi.fuStatic();
        Fu.fuStatic();
    }
}
class Fu {
    protected void fu() {
    }
    public static void fuStatic() {
        System.out.println("父类的静态方法");
    }
}
class Zi extends Fu {
    @Override
    protected void fu() {
    }
   // @Override
    public static void fuStatic() {
        System.out.println("子类的静态方法");
    }
}
public class Iphone extends Phone{
    //ctrl+O 重写父类的方法
    @Override //注解 可以检测该方法,是否是重写父类的方法
    public void call() {
        System.out.println("视频打电话");
    }

关键字final

final:最终的。可以修饰变量,可以修饰成员方法,以及类。

final修饰变量,变量改为常量。常量名一般大写。

final修饰类,此类不能被继承。

final修饰方法,此方法不能被重写了,子类只能继承使用

final修饰引用类型,指的是地址值不能再次改变。

package demo3;
public class text0 {
    public static final boolean B=true;

    public static void main(String[] args) {
        final int num=100;
        System.out.println(num);
        final double A=3.14; //自定义常量
        System.out.println(text0.B);
        Son son = new Son();
        son.show();
        son.test();
        System.out.println("========================");
        final Son son1 = new Son();
    }
}
final class Fu{
}
class Father{
    public void show(){}
    public final void test(){
        System.out.println("最终的方法。子类继承下来使用,子类不能重写");
    }
}
class Son extends Father{
    @Override
    public void show() {
        super.show();
    }
}

多态

运行时绑定

动态绑定:多态最重要的

静态绑定:代码在编译期时我们就知道他输出什么

指的是一种事物,在不同的时期,表现的不同的状态。

多态的继承:前提要有继承,没有继承无从谈起

多态要有重写,当然不重写,语法不报错,但是失去了多态的意义

父类引用指向子类对象

类的初始化过程:jvm加载的最后一步

顺序:
1.静态代码模块static,父子类顺序执行----->2.父类非静态代码块(父类静态代码块执行后,不会执行子类的非静态代码块,会执行父类的构造函数)-------->子类的非静态的代码块------>子类的构造函数
------->其他

成员方法会发生多态,成员变量不发生多态

多态中的成员访问方法

采用多态的形式,去访问成员变量,访问的是父类的成员变量。

访问构造方法,会访问父类的构造方法。

多态形式访问成员方法的特点,如果子类没有重写父类的方法,就以父类的方法为准,如果重写了,以子类重写之后的为准

A:多态中的成员访问特点
a:成员变量
编译看左边,运行看左边。
b:构造方法
创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。
c:成员方法
编译看左边,运行看右边。
d:静态方法
编译看左边,运行看左边。
(静态和类相关,算不上重写,所以,访问还是左边的)
B:案例演示

package demo3;
public class text0 {
        public static void main(String[] args) {
            Fu fu=new Zi();
            System.out.println(fu.num);
            fu.show();
            System.out.println("=========================");
            fu.fuJingTai();
            Fu.fuJingTai();
        }
    }
    class Fu{
        int num=20;
        public Fu() {
            System.out.println("父类的构造方法执行了");
        }
        public void show(){
            System.out.println("父类的show方法");
        }
        public static void fuJingTai() {
            System.out.println("父类的静态方法");
        }
    }
    class Zi extends Fu{
        int num=200;
        int aa=10;
        public Zi() {
            super();
            System.out.println("子类的构造方法执行了");
        }
        @Override
        public void show() {
            System.out.println("zishow  ");
        }
    }

多态的好处

提高代码的复用性,维护性,扩展性。

public class MyTest {
    public static void main(String[] args) {
        Fu fu = new Zi();
        fu.show();
         //fu.method();
        //如果要调用子类特有的方法,我们可以向下转型。
        Zi zi= (Zi) fu;
        zi.method();
        //向上转型:把子类型,转换成父类型。多态就是向上转型。
    }
}

class  Fu{
    public void show(){
        System.out.println("父类的show方法");
    }
}

class Zi extends Fu{
    @Override
    public void show() {
        System.out.println("我重写了父类的show方法");
    }

    public void method(){
        System.out.println("这是子类特有的一个方法");
    }
}

弊端:

不能使用子类的特有功能

多态中的内存图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SHNUXX5F-1587648676920)(C:\Users\LCH\Desktop\JAVA\DAY9\多态的内存图_wps图片.png)]

在Java中,实现多态的方式有两种,一种是编译时多态,另外一种是运行时多态,编译时的多态是通过方法的***重载***实现的,而运行时多态是通过方法的***重写***实现的。

方法的重载是指在同一个类中,有多个方法名相同的方法,但是这些方法有着不同的参数列表,在编译期我们就可以确定到底调用哪个方法。

方法的重写,子类重写父类中的方法(包括接口的实现),父类的引用不仅可以指向父类的对象,而且还可以指向子类的对象。当父类的引用指向子类的引用时,只有在运行时才能确定调用哪个方法。
rintln(“父类的show方法”);
}
}

class Zi extends Fu{
@Override
public void show() {
System.out.println(“我重写了父类的show方法”);
}

public void method(){
    System.out.println("这是子类特有的一个方法");
}

}


弊端:

不能使用子类的特有功能



**多态中的内存图**

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200423213211605.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2NzY3MTgw,size_16,color_FFFFFF,t_70)


在Java中,实现多态的方式有两种,一种是编译时多态,另外一种是运行时多态,编译时的多态是通过方法的***重载***实现的,而运行时多态是通过方法的***重写***实现的。

方法的重载是指在同一个类中,有多个方法名相同的方法,但是这些方法有着不同的参数列表,在编译期我们就可以确定到底调用哪个方法。

方法的重写,子类重写父类中的方法(包括接口的实现),父类的引用不仅可以指向父类的对象,而且还可以指向子类的对象。当父类的引用指向子类的引用时,只有在运行时才能确定调用哪个方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值