第七章 面向对象的编程
第七章 面向对象的编程
基本概念
类成员变量
- 所有的类共享这一个变量,static修饰
类方法
static修饰,类名调用
实例方法
实例成员变量
接口和枚举类型
接口
- 接口之间可以继承与扩展
- 一个类可以实现多个接口(从而具备了多个接口中的方法)
- 一个接口可以有多种实现类
接口和类的关系
-
接口:确定 ADT 规约
-
不要有具体实现
-
接口没有构造函数,可以使用静态工厂方法代替
-
接口是immutable的,那么其实现类也该如此
-
客户端需要知道接口的具体实现类的名字
-
default方法,在接口中统一实现某些功能,无需在各个类中重复实现它。
-
-
可以定义常量,默认都是public static final
-
-
类:实现 ADT,也可以不需要接口直接使用类作为 ADT ,既有 ADT 定义也有 ADT 实现
继承和重写
继承
-
严格继承
- 子类只能添加新方法,无法重写超类中的方法
- 在Java中用关键字final修饰方法实现
重写(Overriding)
-
相同的函数名,相同的参数,相同的返回值
- 只要有相同的函数名和参数列表,就认为是重写,此时必须要有相同的返回类型(或者返回类型的实现类或子类型),否则编译不通过
-
编译时决定能否调用,确定其声明类型中是否有这个函数,运行时调用这个实际类型的方法
-
父类型中的被重写函数体不为空:意味着对其大多数子类型来说,该方法是可以被直接复用的。
-
对某些子类型来说,有特殊性,故重写父类型中的函数,实现自己的特殊要求
-
如果父类型中的某个函数实现体为空(方法名(){没有内容}),意味着其所有子类型都需要这个功能,但各有差异,没有共性,在每个子类中均需要重写。
-
重写之后,利用super()复用了父类型中函数的功能,并对其进行了扩展,其中构造函数的super()必须是第一条语句,同一个类中,调用构造器可用this()
-
重写的时候,不要改变原方法的本意
-
子类中重写方法的可见性高于父类方法
- 父类public,子类只能public
- 可见性 public>protected>default>private
-
抛出的异常只能是父类抛出异常类及其子类的子集
抽象类
-
抽象方法
- 有声明,没实现体
- 关键字 abstract
-
抽象类
- 至少一个抽象方法
- 接口是一个只有抽象方法的抽象类
-
如果某些操作是所有子类型都共有,但彼此有差别,可以在父类型中设计抽象方法,在各子类型中重写(对比父类型使用空实现体)
多态(Polymorphism)
三种多态
-
特殊多态
-
函数重载(Overloading)
-
多个方法具有同样的名字,但有不同的参数列表
-
价值
- 方便 client 调用, client 可用不同的参数列表,调用同样的函数
-
静态多态
- 根据参数列表进行最佳匹配
- 静态类型检查
- 在编译阶段时决定要具体执行哪个方法 (static type checking)
-
与之相反,overridden方法则是在运行时进行动态检查
-
重载规则
-
必须
- 相同的函数名
- 不同的参数列表(有顺序,即使参数类型集合相同,不同顺序也算重载)
-
可选
- 相同/不同的返回值类型
- 相同/不同的public/private/protected
- 相同/不同的异常
-
可以在同 一个类内重载,也可在子类中重载(发生在父类和子类之间)
- 如果在子类型中重载,用父类型的声明是调用不到的,编译器报错
-
-
-
-
参数化多态
-
泛型
-
它能够以通用方式定义函数和类型,以便它基于运行时传递的参数工作,即允许静态类型检查而无需完全指定类型。
-
泛型编程
-
泛型的父子关系体现在泛型的包含上
-
List 和 List 无继承关系,前者不是后者的父类
-
List是ArrayList的父类
-
List<?>是所有的父类
- List<? extends Animal> Animal及其子类 上界通配符
- List<? super Animal> Animal及其父类 下界通配符
-
-
运行时泛型消失了,不能使用 instanceof() 检查泛型类型
-
不能创建泛型数组
- Pair[] foo = new Pair[42] 相当于Pair[] foo,可插入Pair类型
-
-
-
子类型多态、包含多态
-
继承
- B是A的子类型,那么B是A,A能做的B全能做
- 子类型的规约不能弱化超类型的规约
- LSP可替换原则
-
子类型多态
-
父类引用不同子类,不同类型的对象可以统一的处理而无需区分,从而隔离了“变化”
-
a.getClass()
- 获取a运行时的类
-
a instanceof B
- B只要是a运行时的类或者祖先类都为true
-
-
重要的Object方法
toString()
equals()
注意是Object o,否则没有重写
hashCode()
-
-
效率较低,但其他方面同样好!
设计好的类
写immutable类
- 不要提供任何修改器
- 确保没有方法可以被重写
- 所有字段有final
- 所有字段用private
- 确保mutable部分安全(没有表示暴露)
- 实现toString(), hashCode(), clone(), equals()方法
什么时候使用immutable
-
总是,除非有充分的理由不这样做
-
让小的值的类是immutable
- 例如自己定义的Color, PhoneNumber, Unit,复制代价不高,不怎么会发生变化的
- Date是mutable,经常会出错,所以long代替它
什么时候使用mutable
- 类表示状态发生变化的实体
- 如果类必须是可变的,则最小化可变性