07 - 面向对象程序设计(抽象类&接口)🦑
抽象类(abstract class)
java 中凡是普通类都具备实例化对象的能力,因为一个类具备了实例化对象的一些必要信息,比如属性,比如行为;但是有些时候,当一个类中信息不足以描述一个具体对象时,此时该类就应该考虑定义为抽象类。
java 中的抽象类中所包含的信息,不足以描述一个具体对象,抽象类的内部成分由以下信息构成:
- 属性
- 构造器
- 行为
- 已实现
- 未实现(抽象方法)
抽象类基本案例
语法
public abstract class 类名称{
//属性定义
//方法定义
//抽象方法定义
public abstract 返回值类型 方法名(参数列表);
}
案例:
/**
* 抽象类
* @author mrchai
*/
public abstract class Animal {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//抽象方法
public abstract void eat();
public abstract void sleep();
}
Dog 类:
public class Dog extends Animal{
//实现方法
public void eat() {
System.out.println("吃骨头");
}
//实现方法
public void sleep() {
System.out.println("睡狗屋");
}
}
特点
- 抽象类必须使用 abstract 修饰
- 抽象类存在构造器,但是无法实例化(可以使用匿名内部类创建子类对象)
- 抽象类中通常会包含抽象方法
- 抽象类的存在一般是需要由子类继承,子类一旦继承了抽象类,则子类必须实现父类中的抽象方法(除非子类也是抽象类)
- 抽象类允许继承其他抽象类,但是也只能单继承,可以通过多重继承的方式实现多继承
- abstract 只能修饰类和方法
设计模式之模板方法(Template Method)
模板方法指的是对某些方法实现,另外对于一些方法定义为抽象,在实现方法中调用未实现的方法(定义好算法的骨架,具体实现由子类完成)
例如:银行计算利息,都是利率乘以本金和存款时间,但各种存款方式计算利率的方式不同,所以,在账户这个类的相关方法里,只搭出算法的骨架,但不具体实现。具体实现由各个子类来完成。
账户类(Account.java):
public abstract class Account {
//本金
private double money;
//利息
private double interest;
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
//定义好算法的实现骨架
public double getInterest() {
return money * getInterestRate();
}
public void setInterest(double interest) {
this.interest = interest;
}
/**
* 返回利率
* @param time
* @return
*/
public abstract double getInterestRate() ;
}
活期账户类(ActiveAccount.java):
/**
* 活期账户
* @author mrchai
*
*/
public class ActiveAccount extends Account{
//总存款月数
private int month;
//基础利率
private double base;
public ActiveAccount(int month,double base) {
super();
this.month = month;
this.base = base;
}
@Override
public double getInterestRate() {
return month * base;
}
}
定期账户类(FixedAccount.java):
/**
* 定期账户
* @author mrchai
*/
public class FixedAccount extends Account{
private int year;
private double base;
public FixedAccount(int year, double base) {
super();
this.year = year;
this.base = base;
}
@Override
public double getInterestRate() {
return year * base * 2;
}
}
测试类:
public class TestAccount {
public static void main(String[] args) {
ActiveAccount a1 = new ActiveAccount(5, 0.0001);
a1.setMoney(50000);
FixedAccount a2 = new FixedAccount(5, 0.03);
a2.setMoney(50000);
System.out.println(a1.getInterest());
System.out.println(a2.getInterest());
}
}
接口(interface)
接口是一种比抽象类更纯粹的抽象;因为内部只能够存在常量以及未实现的方法(JDK8 以前),接口通常用于定义一些未实现方法的集合,但是不对法方法具体实现,具体的实现通常是由实现类完成,接口具备以下特征:
- 接口不存在构造器,因此无法实例化
- 接口允许继承接口,可以同时继承多个接口
- 一个类可以实现多个接口,但是必须要同时实现所有接口的方法(除非抽象类)
- 抽象类也实现接口
- JDK8 中对接口有其他新增特性(默认方法,静态方法,函数式接口)
语法
public interface 接口名称{
//常量定义
//方法的声明(不含实现)
}
/**
* 接口即标准
* USB接口:只是一种标准的定义,不包含具体实现
* 一流的公司定义标准 做架构
* 二流的公司卖服务 写框架
* 三流的公司卖产品 写CRUD
*
* 定义一个接口
* @author mrchai
*/
public interface Flyable {
//默认编译器会将以下代码完善成: public static final String msg = "hello";
String msg = "hello";
//编译器会将以下代码自动完善:public abstract void fly()
void fly();
}
抽象类和接口区别
- 抽象类是一种类结构,接口是一种行为准则
- 抽象类中包含类的所有特征,同时包含抽象方法;接口只能有常量和未实现的方法
- 抽象类由子类通过 extends 进行扩展;接口由实现类通过 implements 扩展
- 子类只能继承一个抽象类;一个类可以实现多个接口
- 抽象类能且只能继承一个父类;接口可以继承多个接口,接口不能继承任何类
- 抽象类是对类(名词)的一种抽象;接口是对行为(动词,形容词)的抽象,接口是一种特殊的抽象类
多态详解(polymorphism)
多态的体现包含两种层面:
- 方法层面(重写和重载)
- 属性层面
- 父类引用指向子类对象
- 子类引用指向父类对象(原本就是子类)
多态也称之为动态绑定:在运行期间动态为引用变量绑定具体的对象数据