抽象与接口
1. 抽象
在第一周就有一个Shape类的例子。这个类有很多的子类,每个子类也都实现了父类的方法。实际上父类Shape只是一个抽象的概念而并没有实际的意义。如果请你画一个圆,你知道该怎么画;如果请你画一个矩形,你也知道该怎么画。但是如果我说:“请画一个形状,句号”。你该怎么画?同样,我们可以定义Circle类和Rectangle类的draw(),但是Shape类的draw()呢?
Shape类表达的是一种概念,一种共同属性的抽象集合,我们并不希望任何Shape类的对象会被创建出来。那么,我们就应该把这个Shape类定义为抽象的。我们用abstract关键字来定义抽象类。抽象类的作用仅仅是表达接口,而不是具体的实现细节。抽象类中可以存在抽象方法。抽象方法也是使用abstract关键字来修饰。抽象的方法是不完全的,它只是一个方法签名而完全没有方法体。
如果一个类有了一个抽象的方法,这个类就必须声明为抽象类。如果父类是抽象类,那么子类必须覆盖所有在父类中的抽象方法,否则子类也成为一个抽象类。一个抽象类可以没有任何抽象方法,所有的方法都有方法体,但是整个类是抽象的。设计这样的抽象类主要是为了防止制造它的对象出来。
抽象类的特点:
- 抽象类和抽象方法必须用
abstract
关键字:abstract class Animal { }
- 抽象方法不能有方法体:
public abstract void eat();
(区分 空方法体 和 没有方法体) - 抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
- 抽象类不能实例化(因为他不是具体的),但是支持具体子类的多态(向上转型)
- 抽象类有构造方法,但是不能实例化,构造方法的作用是:用于子类访问父类数据的初始化
- 抽象类的子类:
- 如果不想重写所有抽象方法,这时候子类仍是抽象类
- 重写所有的抽象方法,子类是一个具体的类
抽象类的成员的特点:
成员变量:既可以是变量,也可以是常量
构造方法:有,但作用是用于子类访问父类的数据的初始化
-
成员方法:
既可以是抽象的,也可以是非抽象的
抽象方法,强制要求子类做的事情(必须被子类重写)
非抽象方法,子类继承的事情,提高代码的复用性
abstract
不能和final
,private
,static
共存
抽象类不能制造对象
-
但是可以定义变量
- 任何继承了抽象类的非抽象类的对象,可以赋给这个变量
- 即任何子类的对象,都可以由一个抽象父类的引用变量来引用
继承自抽象类的子类,必须覆盖/实现父类中的所有抽象函数(否则成为抽象类,不能制造对象)
- 抽象 有两种概念:
- 与具体相对:表示一种概念而非实体
- 与细节相对:表示一定程度上而忽略细节着眼大局
2. 数据与表现分离
- 程序的业务逻辑与表现无关
- 表现可以是图形的,也可以是文本的
- 表现可以是本地的也可以是远程的
- View 和 Filed 的关系
- 表现与数据的关系
- View只管根据Field画出图形
- Field只管数据的存放
- 一旦数据更新以后,通知View重新画出整个图形
- 不用去精心设计哪个局部需要更新
- 简化了程序逻辑
-
责任驱动的设计:
-
将程序要实现的功能,分配到合适的类/对象中,是设计中非常重要的一环
(什么类 做什么事情)
-
- 遵循: 可拓展性原则,分离逻辑层和数据层,即分离数据和表现
3. 接口 (可拓展性 用于功能拓展)
类中的额外的功能可以通过实现接口来实现 implement interface
联想 驯兽师 锻炼出 部分猫狗的特殊能力
接口的特点:
- 接口的定义:
interface 接口名 { }
(没有class
) - 接口的实现:
class 类名 implements 接口名 { }
- 接口是一种特殊的抽象类,不能被实例化(多态向上造型)
- 接口的子类:具体类实现接口:必须覆盖接口的所有方法
- 经常在接口的实现类 会加上后缀
-Impl
接口的成员特点 (区别抽象类)
成员变量:默认为静态常量
public static final
(建议自己手动给出)构造方法:接口没有构造方法
-
成员方法:接口方法不能带有主体(全都是抽象方法)(jdk1.8可以有普通方法)
默认修饰符
public abstract
-
接口规定了长什么样,但不管里面有什么
- 接口的实现使用
implements
- 接口的实现使用
类的继承用
extends
, 接口的实现用implements
一个类可以实现很多接口
接口可以继承接口,但不能继承类
一个类可以同时继承父类并且实现接口
接口不能实现接口
类与接口关系
- 类与类:继承关系,只能单继承
- 类与接口:实现关系,可以单实现,也可以多实现
- 接口与接口:继承关系,可以单继承,也可以多继承
抽象类 与 接口 区别:
- 成员区别:(成员变量,构造方法,成员方法)
- 关系区别:如上所述,继承与实现
-
设计理念的区别:
- 抽象类:继承体现的是 “is a” 的关系,共性功能
- 接口:接口被实现体现的是 “like a” /“tend to” 的关系, 拓展功能 (USB)
比如 猫狗案例: 加入跳高的额外功能
猫狗共性,抽取出父类(抽象类)Animal;(名字,年龄,吃饭,睡觉)
跳高的功能是一个新的拓展功能,所以我们定义一个接口:
接口:跳高
interface Jumping() { public abstract jump(); }
部分猫
extends Cat implements Jumping { }
:实现跳高;部分狗
extends Dog implements Jumping { }
:实现跳高;
面向接口的编程方式
- 两个东西之间的连接
- 当你需要别人为你提供服务,或者需要别的东西的时候,你不是先定义一个类,而是先定义一个接口
- 所有想要放到filed中的都是Cell
- 设计程序时,先定义接口,再实现类
- 任何需要在函数间传入传出的一定是接口,而不是具体的类
- 是Java成功的关键之一,因为极其适合多人同时写一个大程序
- 每个人只要提出要求,只需要提出一个接口,每个人根据这个接口去实现
- 接口分隔开每个程序的不同部
- 也是Java被批评的要点之一,因为代码量膨胀起来很快
- 分析:从具体到抽象
- 实现:从抽象到具体
- 使用:具体