HIT-SC-Chapter Seven
目录
HIT-SC-Chapter Seven
Object-Oriented Programming (OOP)
1 Basic concepts: object, class, attribute, and method
(1) 类的静态变量/方法与实例变量/方法
class variable- 与类相关联的变量,而不是类的实例。
class method- 还可以将方法与类关联
- 要引用类变量和方法,需要将类名和类方法或类变量的名称与一个句点(' .')连接在一起。
instance methodandinstance variables- 不是类方法或类变量的方法和变量
- 要引用实例方法和变量,必须从类的实例引用方法和变量
- 类变量和类方法与一个类关联,并且每个类出现一次。使用它们不需要创建对象。
- 实例方法和变量在类的每个实例中出现一次。
![image-20220609165218947]()
2 Interface
-
Java的接口是设计和表达ADT的一种有用的语言机制,它的实现是实现该接口的类
- An interface in Java is a list of method signatures, but no method bodies.
- A class implements an interface if it declares the interface in its implements clause, and provides method bodies for all of the interface’s methods.
- An interface can extend one or more others
- A class can implement multiple interfaces
![image-20220609165440843]()
-
VS. Classes
- 接口:确定ADT规约;类:实现ADT
- 也可以不需要接口直接使用类作为ADT,既有ADT定义也有ADT实现
- 公共类方法像接口方法一样可用
- 从其他类直接访问的公共字段
- 实际中更倾向于使用接口来定义变量
- 防止依赖于实现细节
- 支持实现的变化
- 对变量和参数使用接口类型
-
![image-20220609165941405]()
- Java接口不能有构造函数。
-
client需要直到该接口某个具体实现类的名字
- 打破了抽象边界,接口定义中没有包含constructor,也无法保证所有实现类中都包含了同样名字的constructor。
- 改进:
- 使用静态工厂代替构造函数
![image-20220609170933240]()
-
Using default methods in an interface
- 接口中的每个非static 和default方法在所有类中都要实现
- 通过default方法,在接口中统一实现某些功能,无需在各个类中重复实现它
- 以增量式的为接口增加额外的功能而不破坏已实现的类
![image-20220609171211902]()
3 Inheritance and Overriding
(1) Overriding
- 可重写方法
- 允许重新实现的方法。
- 在Java中,方法默认是可重写的,即没有特殊的关键字。
- Strict inheritance (严格继承:子类只能添加新方法,无法重写超类中的方法)
- The subclass can only add new methods to the superclass, it cannot overwrite them
- 如果一个方法在Java程序中不能被重写,那么它必须以关键字final作为前缀。
![image-20220609182651716]()
- 方法重写是一种语言特性,它允许子类或子类对已由其父类或父类提供的方法的特定实现。
- The same name, same parameters or signature, and same return type.
- 被执行的方法的版本将由调用它的对象决定。(对象是父类/子类的实例)
- 在running时确定
![image-20220609182845523]()
- 如果父类型中的某个函数实现体为空,意味着其所有子类型都需要这个功能,但各有差异,没有共性,在每个子类中均需要重写。
![image-20220609183508448]()
- 当子类包含覆盖超类方法的方法时,它还可以使用关键字super调用超类方法。
- 重写超类的constructor()时,对超类构造器的调用必须放到第一条语句。
- 重写超类的constructor()时,对超类构造器的调用必须放到第一条语句。
- Bad Use of Overwriting Methods
- 重写的时候,不要改变原方法的本意
- 重写方法的方法名和方法参数(参数数量,参数类型)必须完全一致。
(2) Abstract Class
- Abstract Methods
- A method with a signature but without an implementation (also called abstract operation)
- Abstract class
- 包含至少一个抽象方法的类称为抽象类
- 接口:只有抽象方法的抽象类
- Concrete class $\rightarrow$ Abstract Class $\rightarrow$ Interface
- 如果某些操作是所有子类型都共有,但彼此有差别,可以在父类型中设计抽象方法,在各子类型中重写
- 所有子类型完全相同的操作,放在父类型中实现,子类型中无需重写。
- 有些子类型有而其他子类型无的操作,不要在父类型中定义和实现,而应在特定子类型中实现。
4 Polymorphism, subtyping and overloading
多态、子类型、重载
(1) Three Types of Polymorphism
- Ad hoc polymorphism (特殊多态):
- 当一个函数根据有限范围内个别变量指定的类型和组合表示不同的、可能是异构的实现时。
- function overloading (功能重载).
- Parametric polymorphism (参数化多态)
- 在编写代码时没有提到任何特定类型,因此可以透明地与任意数量的新类型一起使用。
- 在面向对象编程社区中,这通常被称为泛型或泛型编程。
- Subtyping (also called subtype polymorphism or inclusion polymorphism 子类型多态、包含多态)
- 当一个名称表示由某个公共超类相关的许多不同类的实例时。
(2) Ad hoc polymorphism and Overloading
特殊多态
-
当函数处理几种不同的类型(这些类型可能不表现为通用的结构),并且每种类型的行为方式可能不相关时获得。
-
![image-20220609185439688]()
-
Overloading 重载
- 重载方法允许您在类中重用相同的方法名,但使用不同的参数(以及可选的不同返回类型)。
- 方便client用不同的参数列表,调用相同的函数
- Overload也可以发生在父类和子类之间
- 函数重载是用不同的实现创建多个同名方法的能力。
- 静态多态
- 根据参数列表进行最佳匹配
- 静态类型检查
- 在编译阶段时决定要具体执行哪个方法 (static checking)
- 相反,overridden methods则是在run-time进行dynamic checking!
- rules
- 重载的函数必须根据arity值或数据类型而不同
- 不同的参数列表
- 相同/不同的返回值类型
- 相同/不同的public/private/protected
- 异常
- 可以在同一个类内重载,也可在子类中重载
- 重载方法允许您在类中重用相同的方法名,但使用不同的参数(以及可选的不同返回类型)。
-
![image-20220609190351791]()
-
![image-20220609190432378]()
-
![image-20220609190609616]()
-
![image-20220609190647097]()
-
![image-20220609200613333]()
-
Overriding vs. Overloading
![image-20220609201236565]()
- compile_time/static checking
- run_time/dynamic_checking
(3) Parametric polymorphism and Generic programming
- 当一个函数在一系列类型上一致工作时,得到参数多态性;这些类型通常表现出一些共同的结构。
- 它具有以泛型方式定义函数和类型的能力,以便在运行时根据传递的参数工作,也就是说,允许在不完全指定类型的情况下进行静态类型检查
- This is what is called “Generics (泛型)” in Java.
- 泛型编程是一种编程风格,在这种编程中,数据类型和函数按照要指定的类型编写,然后在需要特定类型作为参数提供时实例化这些类型。
- 泛型编程的核心思想是从具体的、有效的算法中抽象出来,以获得泛型算法,这些泛型算法可以与不同的数据表示相结合,从而生成各种各样的有用软件。
- Type variables
- Using <>, the diamond operator, to help declare type variables.
- For example:
![image-20220609202129406]()
- Generic Interfaces
- Generic interface, non-generic implementation泛型接口,非泛型的实现类
- Generic interface, generic implementation.泛型接口,泛型的实现类
- Generic interface, non-generic implementation泛型接口,非泛型的实现类
- some details
- Can have multiple type parameters
- e.g., Map<E, F>, Map<String, Integer>
- Wildcards 通配符,只在使用泛型的时候出现,不能在定义中出现
- 泛型类型信息被擦除(即仅在编译时)
- Cannot use instanceof() to check generic type 运行时泛型消失了
- 无法创建泛型数组
- Pair
[] foo = new Pair [42]; // won't compile
- Pair
- Can have multiple type parameters
(4) Subtyping Polymorphism
- 继承和子类型:层次结构的一瞥
![image-20220609202617917]()
- 代码重用,建模灵活性
- 每个类只能直接扩展一个父类;一个类可以实现多个接口。
- Subtypes
- “B is a subtype of A” means “every B is an A.”
- In terms of specifications: “every B satisfies the specification for A.”
- 如果B的规范至少与a的规范一样强,那么B是a的一个子类型。
- 当我们声明一个实现接口的类时,Java编译器会自动执行这个要求的一部分:它确保a中的每个方法都出现在B中,具有兼容的类型签名。
- 如果不实现A中声明的所有抽象方法,类B无法实现接口A
- 子类型的静态检查 static checking
- 但是编译器不能检查我们是否在其他方面削弱了规范
- 加强对某一方法某些输入的前提条件
- 削弱一个后置条件
- 削弱接口抽象类型向客户端发布的保证。
- 如果在Java中声明子类型(例如,实现一个接口),那么必须确保子类型的规范至少与父类型的规范一样强。
- 但是编译器不能检查我们是否在其他方面削弱了规范
- 子类型的规约不能弱化超类型的规约。
- 子类型多态:不同类型的对象可以统一的处理而无需区分
- 每个对象的行为取决于它的类型(例如,如果你添加了新类型的帐户,客户端代码不会改变)
- 隔离变化
- 每个对象的行为取决于它的类型(例如,如果你添加了新类型的帐户,客户端代码不会改变)
- Liskov Substitution Principle (LSP)
- 如果S是T的一个子类型,那么T类型的对象可以用S类型的对象替换(也就是说,T类型的对象可以用S子类型的任何对象替换),而不改变T的任何理想性质。
- Reusability
-
instanceof
-
测试对象是否属于给定类的对象
-
avoid instanceof() if possible, and never(?) use instanceof() in a superclass to check type against subclass.
-
Advice
- Avoid down_casting types
- Never(?) downcast within superclass to a subclass
- spec
-
5 Some important Object methods in Java
(1)Overriding Object methods
- equals() – true if the two objects are “equal”
- hashCode() – a hash code for use in hash maps
- toString() – a printable string representation
- ugly and uninformative
- Always override unless you know in won’t be called
- equals & hashCode – identity semantics
- You must override if you want value semantics
- Otherwise don’t
- Overriding toString()
![image-20220609204927175]()
![image-20220609204934714]()
- equals它的作用也是判断两个对象是否相等,如果对象重写了equals()方法,比较两个对象的内容是否相等;如果没有重写,比较两个对象的地址是否相同,价于“==”。
6 Designing good classes
-
an immutable class
-
![image-20220609205520039]()
-
![image-20220609205547644]()
![image-20220609205604257]()
-
When to make classes mutable
- If class must be mutable, minimize mutability
- Always, unless there's a good reason not to
7 History of OOP
……
SUM






























浙公网安备 33010602011771号