JAVA基础语言面向对象之——多态、抽象类、接口

JAVA基础语言面向对象之——多态、抽象类

多态

  • 多态的概念:
    ​ “is-a"规则可以用来判断是否应该将数据设计为继承关系,它表明子类的每个对象也是父类的对象,例如:每个猫都是动物,因此将Cat类设计为Animal类的子类是显而易见的,反之不然。
    ​ “is-a”规则的另一种表述法是置换法则,它表明程序中出现父类对象的任何地方都可以用子类对象来置换。例如:可以将一个子类的对象赋给父类的引用。Cat cat = new Cat(); Animal animal = new Cat();。在java中,将父类的引用赋给子类对象是不允许的。
    ​ 在JAVA程序设计语言中,对象变量是多态的。一个Animal类型变量既可以引用一个Animal类型对象,也可以引用一个Animal类的任何一个子类的对象,例如Animal animal = new Animal(); Animal animal = new Cat(); Animal animal = new Dog();等。

  • 多态的前提:
    a:要有继承关系。
    b:要有方法重写。 其实没有也是可以的,但是如果没有这个就没有意义。
    c:要有父类引用指向子类对象。父 f = new 子();

  • 案例演示:
    ​ 多态的体现

    public class MyTest {
        public static void main(String[] args) {
            //多态,父类引用指向的是子类对象
            Animal an=new Cat();
            an.sleep();
            an.eat();
            an.show();
        }
    }
    
    class Animal{
        public void eat(){
            System.out.println("吃饭");
        }
    
        public void sleep() {
            System.out.println("睡觉");
        }
    
        public void show() {
            System.out.println("父类中的show方法");
        }
    }
    
    class Cat extends Animal{
        @Override
        public void eat() {
            System.out.println("猫爱吃鱼");
        }
    
        @Override
        public void sleep() {
            System.out.println("猫爱白天睡觉");
        }
    }
    

多态中的成员访问

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

  • B:案例演示:
    多态中的成员访问特点

    public class MyTest {
        public static void main(String[] args) {
            Fu fu = new Zi();   
            System.out.println(fu.num);    //以多态的形式来访问成员变量   
            fu.show();     //多态的形式访问成员方法,动态绑定
            Fu.hehe();     //静态绑定
        }
    }
    
    class Fu{
        int num = 100;
        public void show(){
            System.out.println("父类的show方法");
        }
        public static void hehe(){
            System.out.println("父类的静态方法");
        }
    }
    
    class Zi extends Fu{
        int num=10;
        
        @Override
        public void show() {
            System.out.println("子类重写过后的show方法");
        }
    
        public static void hehe() {
            System.out.println("子类的静态方法");
        }
    }
    
    运行结果:
    100
    子类重写过后的show方法
    父类的静态方法
    
    • 此程序的内存图如下:
      在这里插入图片描述
  • C:绑定机制:
    ​ 静态绑定:调用成员方法的时候,如果方法是private、static、final或构造方法,那么编译器将可以准确地知道应该调用哪个方法。 例如:Fu.hehe();调用父类的静态方法。
    ​ 动态绑定:调用成员方法的时候,a)若存在方法重载,编译器将根据参数的实际类型寻找调用的方法(此过程称为重载解析)。b)若子类对父类的方法进行重写,则调用此方法的时候,执行子类重写后的方法。此类过程称为动态绑定。例如:fu.show(); 调用的时候执行子类重写后的show方法。
    ​ 动态绑定的一个重要特性:无需对现存代码进行修改,就可以对程序进行扩展。假设新增一个新类S on,并且变量fu有可能引用这个类的对象,我们不需要对包含调用fu.show()的代码进行重新编译,只需在此类中重写show()方法。

  • 多态的好处:
    ​a:提高了代码的维护性(继承保证)
    ​ b:提高了代码的扩展性(由多态保证)

  • 多态的弊端:
    ​ 父类引用不能访问子类独有的功能和属性。
    ​ 解决办法:向下转型,把父类的引用强制转换为子类的引用(也称为强制类型转换)。
    案例演示:多态的向下转型

    public class MyTest {
        public static void main(String[] args) {
            Cat cat = new Cat();
            Animal an=cat; //多态就是向上转型
            an.eat();
            Cat c= (Cat) an; //向下转型
            c.eat();
            c.cacheMouse();
    
            Dog dog = new Dog();
            an=dog;
            Dog d= (Dog) an; //向下转型
            d.lookDoor();
            an.eat();
           
            Tiger t= (Tiger) an;
            t.goSwimming();
        }
    }
    
    class Animal{
        public void eat(){
            System.out.println("吃饭");
        }
    }
    
    class Cat extends Animal{
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
        public void cacheMouse(){
            System.out.println("猫抓老鼠");
        }
    }
    
    class Dog extends Animal{
        @Override
        public void eat() {
            System.out.println("狗吃骨头");
        }
        
        public void lookDoor(){
            System.out.println("狗看门");
        }
    }
    
    class Tiger extends Animal{
        @Override
        public void eat() {
            System.out.println("老虎不吃素");
        }
        
        public void goSwimming(){
            System.out.println("老虎去游泳");
        }
    }
    

抽象类

  • A:抽象类概述:
    回想前面我们的猫狗案例,提取出了一个动物类。并且我们在前面也创建过了动物对象,其实这是不对的。为什么呢?因为,我说动物,你知道我说的是什么动物吗?只有看到了具体的动物,你才知道,这是什么动物。
    所以说,动物本身并不是一个具体的事物,而是一个抽象的事物。只有真正的猫,狗才是具体的动物。同理,我们也可以推想,不同的动物吃的东西应该是不一样的,所以,我们不应该在动物类中给出具体体现,而是应该给出一个声明即可。
    ​ 抽象类就是被abstract所修饰的类,父类将所有子类的共性功能向上抽取后,他并不知道,每个子类对这个共性功能的具体实现,所以没有必要在父类中,给出共性功能的具体实现,而是给出声明即可,所谓给出功能的声明,就是将此功能抽象出来,然后强制子类必须重写,抽象的功能。

  • B:抽象类特点:
    a:抽象类和抽象方法必须用abstract关键字修饰
    抽象类格式: abstract class 类名 {}
    抽象方法格式: public abstract void eat();
    b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
    c:抽象类中可以有构造方法,抽象类不能进行实例化,那么要构造方法有什么作用呢?
    用于子类访问父类数据时的初始化
    d:抽象类不能直接实例化那么,抽象类如何实例化呢?
    按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
    e:抽象类的子类
    要么是抽象类
    要么重写抽象类中的所有抽象方法

  • 案例演示:
    假如我们在开发一个系统时需要对员工(Employee) 类进行设计,员工包含3个属性:姓名、工号以及工资(salary)。经理(Manager) 也是员工,除了含有员工的属性外,另为还有一个奖金(bonus) 属性。然后定义工作的方法。

    public class MyTest {
        public static void main(String[] args) {    
            Person p = new Employee();     //抽象类的实例化,采用多态形式
            p.name="张岚";
            p.num=1;
            p.salary=2000;
            System.out.println(p.name+"=="+p.num+"==="+p.salary);
            p.work();
            System.out.println("--------------------");
            p=new Manager();
            p.name = "刘林";
            p.num = 2;
            p.salary = 4000;
            ((Manager) p).bonus=2000;    //向下转型
            System.out.println(p.name+"==="+((Manager) p).bonus+"==="+p.num);
            p.work();
        }
    }
    
    //抽象类Person类
    public abstract class Person {
        public String name;
        public int num;
        public double salary;
    
    	//抽象方法
        public abstract void work();      
    }
    
    public class Employee extends Person{
        @Override    //重写父类中的抽象方法
        public void work() {
            System.out.println("员工敲代码");
        }
    }
    
    public class Manager extends Person{
        public double bonus;
     
        @Override         //重写父类中的抽象方法
        public void work() {
            System.out.println("经理管理员工");
        }
    }
    
  • C:抽象类的成员特点:
    a:成员变量:既可以是变量,也可以是常量。
    b:构造方法:有。用于子类访问父类数据的初始化。
    c:成员方法:既可以是抽象的,也可以是非抽象的。

  • D:抽象类的成员方法特性:
    a:抽象方法 ,强制要求子类做的事情。抽象方法充当占位的角色,它们的具体实现在子类中。
    b:非抽象方法 ,子类继承的事情,提高代码复用性。

    1、一个类如果没有抽象方法,可不可以定义为抽象类 ? 如果可以,有什么意义 ?
        可以, 外界不能直接创建对象
    2、abstract不能和哪些关键字共存 ?
    	不能和private 共存 矛盾;不能和 final 共存 矛盾;不能和 static 共存 没有意义
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值