面向对象三大特征之多态

来源:互联网 发布:java jar 打包 编辑:程序博客网 时间:2024/05/16 18:53

一.多态

1.含义

同一个对象(事物),在不同时刻体现出来的不同状态

2.前提

有继承或实现关系

有方法的重写,其实没有也是可以的,但是如果没有这个就没有意义

有父类或者父接口引用指向之类对象

3.分类

具体类多态(几乎没有)

            class Fu {}            class Zi extends Fu {}            Fu f = new Zi();

抽象类多态(常用)

            abstract class Fu {}            class Zi extends Fu {}            Fu f = new Zi();

接口多态(最常用)

            interface Fu {}            class Zi implements Fu {}            Fu f = new Zi();

4.成员访问特点

成员变量

编译看左,运行看左

构造方法

创建子类对象的时候,访问父类构造方法,完成父类数据的初始化

成员方法

编译看左,运行看右(由于成员方法存在方法重写)

继承的时候:
子类中有和父类中一样的方法,叫重写。
子类中没有父亲中出现过的方法,方法就被继承过来了。

代码示例

class Fu {    public int num = 100;    public void show() {        System.out.println("show Fu");    }    public static void function() {        System.out.println("function Fu");    }}class Zi extends Fu {    public int num = 1000;    public int num2 = 200;    public void show() {        System.out.println("show Zi");    }    public void method() {        System.out.println("method zi");    }    public static void function() {        System.out.println("function Zi");    }}class DuoTaiDemo {    public static void main(String[] args) {        //要有父类引用指向子类对象。        //父 f =  new 子();        Fu f = new Zi();        System.out.println(f.num);        //找不到符号        //System.out.println(f.num2);        f.show();        //找不到符号        //f.method();        f.function();    }}

5.好处

提高代码维护性(由继承保证)

提高代码的扩展性(由多态保证)

6.弊端

父类不能使用子类特有的功能

现象: 子类可以当做父类用,父类不能当做子类用

7.转型

向上转型,从子到父(父类引用指向子类对象)

Fu f = new Zi();

向下转型,从父到子(把父类的引用强制转换为子类的引用)

Zi z = (Zi) f;

ClassCastException:类型转换异常,向下转型中容易出现

代码示例

多态的问题理解:    class 孔子爹 {        public int age = 40;        public void teach() {            System.out.println("讲解JavaSE");        }    }    class 孔子 extends 孔子爹 {        public int age = 20;        public void teach() {            System.out.println("讲解论语");        }        public void playGame() {            System.out.println("英雄联盟");        }    }    //Java培训特别火,很多人来请孔子爹去讲课,这一天孔子爹被请走了    //但是还有人来请,就剩孔子在家,价格还挺高。孔子一想,我是不是可以考虑去呢?    //然后就穿上爹的衣服,带上爹的眼睛,粘上爹的胡子。就开始装爹    //向上转型    孔子爹 k爹 = new 孔子();    //到人家那里去了    System.out.println(k爹.age); //40    k爹.teach(); //讲解论语    //k爹.playGame(); //这是儿子才能做的    //讲完了,下班回家了    //脱下爹的装备,换上自己的装备    //向下转型    孔子 k = (孔子) k爹;     System.out.println(k.age); //20    k.teach(); //讲解论语    k.playGame(); //英雄联盟

7.多态继承中的内存图解

这里写图片描述

8.多态中的对象变化内存图解

这里写图片描述

二.抽象类

1.概述

动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的。 我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类。

2.特点

(1).抽象类和抽象方法必须用abstract修饰

(2).抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类

(3).抽象类不能被实例化

因为抽象类不是具体的,抽象类有构造方法,但是不能被实例化,那么构造方法的作用是?

用于子类访问父类时,

(4). 抽象类的子类

是一个抽象类,无须重写抽象方法
是一个具体的类,必须重写所有的抽象方法

3.成员特点

(1).成员变量

既可以是变量,也可以是常量

(2).构造方法

有,用于子类访问父类数据的初始化

(3).成员方法

既可以是抽象方法,强制要求之类做的事情

也可以是非抽象方法,子类继承的事情,提高代码复用性

4.实例化

靠具体的子类来实现,通过多态的方式

Animal a = new Cat();

5.几个小问题)

(1).抽象类有构造方法,不能实例化,那么构造方法有什么用?

用于子类访问父类数据的初始化

(2).一个类如果没有抽象方法,却被定义成了抽象类,有什么用

为了不让创建对象

(3).abstract不能和哪些关键字共存

final 冲突

private 冲突

static 无意义

三.接口

1.概述

猫钻火圈,狗跳高等功能,不是动物本身就具备的,是在后面的培养中训练出来的,这种额外的功能,java提供了接口表示。

2.特点

(1).接口用关键字interface修饰

interface 接口名 { }

(2).类实现接口用implements修饰

类名 implements 接口名 { }

(3).接口不能实例化

那么,接口如何获取实例化呢? 按照多态的方式,来实例化

(4).接口的实现类

可以是抽象类,但意义不大

可以是具体类,要重写接口中所有的抽象方法(推荐)

3.成员特点

(1).成员变量

只能是常量,默认修饰符: public static final (建议自己手动给出)

(2).构造方法

没有构造方法

(3).成员方法

只能是抽象方法,默认修饰符: public abstract (建议自己手动给出)

4.类与类,类与接口,接口与接口

(1).类与类

继承关系,只能单继承,不能多继承,可以多层继承

(2).类与接口

实现关系,可以单实现,可以多实现

还可以在继承一个类的同时,实现多个接口

(3).接口与接口

继承关系,可以单继承,可以多继承

5.抽象类和接口的区别

(1).成员区别

抽象类

成员变量:可以变量,也可以常量

构造方法:有

成员方法:可以抽象,也可以非抽象

接口

成员变量:只可以常量

成员方法:只可以抽象

(2).关系区别

类与类

继承,单继承

类与接口

实现,单实现,多实现

接口与接口

继承,单继承,多继承

(3).设计理念区别

抽象类

被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。

接口

被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。

代码示例

/*    猫狗案例,加入跳高的额外功能    分析:从具体到抽象        猫:            姓名,年龄            吃饭,睡觉        狗:            姓名,年龄            吃饭,睡觉        由于有共性功能,所以,我们抽取出一个父类:        动物:            姓名,年龄            吃饭();            睡觉(){}        猫:继承自动物        狗:继承自动物        跳高的额外功能是一个新的扩展功能,所以我们要定义一个接口        接口:            跳高        部分猫:实现跳高        部分狗:实现跳高    实现;        从抽象到具体    使用:        使用具体类*///定义跳高接口interface Jumpping {    //跳高功能    public abstract void jump();}//定义抽象类abstract class Animal {    //姓名    private String name;    //年龄    private int age;    public Animal() {}    public Animal(String name,int age) {        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    //吃饭();    public abstract void eat();    //睡觉(){}    public void sleep() {        System.out.println("睡觉觉了");    }}//具体猫类class Cat extends Animal {    public Cat(){}    public Cat(String name,int age) {        super(name,age);    }    public void eat() {        System.out.println("猫吃鱼");    }}//具体狗类class Dog extends Animal {    public Dog(){}    public Dog(String name,int age) {        super(name,age);    }    public void eat() {        System.out.println("狗吃肉");    }}//有跳高功能的猫class JumpCat extends Cat implements Jumpping {    public JumpCat() {}    public JumpCat(String name,int age) {        super(name,age);    }    public void jump() {        System.out.println("跳高猫");    }}//有跳高功能的狗class JumpDog extends Dog implements Jumpping {    public JumpDog() {}    public JumpDog(String name,int age) {        super(name,age);    }    public void jump() {        System.out.println("跳高狗");    }}class InterfaceTest {    public static void main(String[] args) {        //定义跳高猫并测试        JumpCat jc = new JumpCat();        jc.setName("哆啦A梦");        jc.setAge(3);        System.out.println(jc.getName()+"---"+jc.getAge());        jc.eat();        jc.sleep();        jc.jump();        System.out.println("-----------------");        JumpCat jc2 = new JumpCat("加菲猫",2);        System.out.println(jc2.getName()+"---"+jc2.getAge());        jc2.eat();        jc2.sleep();        jc2.jump();        //定义跳高狗并进行测试的事情自己完成。    }}
0 0