浅谈面向对象中的多态

面向对象有三大特征:封装、继承和多态。今天我们来谈谈多态。

多态

多态概述
什么是多态?
每每谈及多态时,总有一种只可意会不可言传的感觉。简单来说多态就是某个事物,在不同时刻表现出来的不同状态。
比如:猫可以是猫的类型,也可以是动物的类型(因为猫也是动物)。
多态的前提

  • 类和类要有继承关系。
  • 要有方法重写。没有也行,但没有的话多态就没有意义了。
  • 要有父类引用指向子类对象。(父类 对象名 = new 子类();)

多态中的成员的访问特点

  • 成员变量的访问特点:编译看左边,运行看左边
  • 成员方法的访问特点:编译看左边,运行看右边
  • 构造方法:创建子类对象时,会先访问父类的构造方法,对父类的数据进行初始化
  • 静态方法的访问特点:编译看左边,运行看左边(静态方法是属于类的,算不上重写,所以访问还是左边的)

多态的好处
可总结如下

  • 提高了代码的维护性(继承)
  • 提高了代码的扩展性(多态)

多态虽然有好处,但是也有弊端。多态的弊端就是不能够访问子类特有的功能。(因为是父类引用指向子类对象)
浅谈面向对象中的多态
在多态的方式下,若要访问子类特有的功能则需要向下转型,即把父类的引用强制类型转换为子类的引用。
浅谈面向对象中的多态
那么有向下转型,就有向上转型,多态就是典型的向上转型,父类引用指向子类对象。

抽象类

抽象类概述
在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。
抽象方法的格式:
修饰符 abstract 返回值类型 方法名();
浅谈面向对象中的多态
抽象类的格式:
abstract class 类名{
}
浅谈面向对象中的多态
那么抽象类有哪些特点呢?

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

抽象类的成员特点

  • 成员变量:既可以是变量,也可以是常量。
  • 构造方法:有构造方法。用于子类访问父类数据的初始化。
  • 成员方法:既可以是抽象的,也可以是非抽象的。

抽象类的成员方法特性

  • 抽象方法:强制要求子类做的事情。子类必须重写父类的抽象方法。
    浅谈面向对象中的多态
  • 非抽象方法:子类继承的事情,提高代码复用性。

一个类如果没有抽象方法,可以定义为抽象类,但是不能创建对象。

接口

何为接口
为了体现事物功能的扩展性,Java中提供了接口来定义一些额外功能(这些额外功能并不是类的对象所共有的,只是一部分对象拥有),并不给出具体实现,当有事物向具备这些额外功能时,就可以实现这个接口

接口的特点

  • 接口用关键字interface表示
    接口的格式为:
    interface 接口名 {
    }
    浅谈面向对象中的多态
  • 类实现接口用implements表示
    格式为:
    class 类名 implements 接口名 {
    }
    这个类,可以叫做接口的子类, 这个接口 可以叫做这个类的父接口。
    浅谈面向对象中的多态
  • 接口不能实例化
    若要实例化,则需要用多态的方式进行实例化
  • 接口的子类:可以是抽象类(但是意义不大);可以是具体类,要重写接口中的所有抽象方法(推荐这样写)

作为接口的子类,有什么要求

  • 要求子类必须重写接口中所有的抽象方法
  • 如果不想重写,那么这个类可以为一个抽象类,将接口中的抽象方法继承即可

接口成员特点

  • 成员变量:只能是常量,并且是静态的。默认修饰符:public static final,但是建议我们在写的时候手动给出。
  • 构造方法:接口没有构造方法。
  • 成员方法:只能是抽象方法。默认修饰符:public abstract,但是建议我们在写的时候手动给出。

类、接口之间的关系

  • 类与类:继承关系,只能单继承,可以多层继承。
  • 类与接口:实现关系,可以单实现,也可以多实现。也可以在继承一个类的同时实现多个接口。
  • 接口与接口:继承关系,可以单继承,也可以多继承。

抽象类和接口的区别
成员的区别

  • 成员变量:
    抽象类中的成员变量既可以是常量,也可以是变量;
    接口中的成员变量只能是静态的常量
  • 成员方法:
    抽象类中的成员方法既可以是抽象的,也可以是非抽象的;
    接口中的成员方法必须是抽象的
  • 构造方法:
    抽象类中有构造方法;
    接口中没有构造方法

关系的区别:

  • 类与类:继承关系,单继承
  • 类与接口:实现关系,单实现和多实现均可
  • 接口与接口:继承关系,单继承和多继承均可

设计理念的区别:

  • 抽象类:被继承 体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
  • 接口:被实现 体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。

JDK1.8之后在接口中提供了用default修饰的方法,可以给出功能的具体实现,子类可以继承下去用

abstract关键字

abstract关键字:抽象的,可以修饰类,也可以修饰方法。
特点

  • abstract 修饰类,此类就不能直接实例化
  • abstract 修饰方法,修饰的方法,要求子类必须重写

abstract和以下关键字不共存:

  • private
    原因:private修饰的成员不能被子类继承,而abstract要求继承成员,并重写方法。
  • final
    冲突的原因同上。
  • static
    不能共存 无意义