Primitive Terms

If you are expecting from me a furniture, then a table will work.

-Inheritance vs. Subtyping (webinar #24)

LSP

The Liskov substitution principle (LSP) is a particular definition of a subtyping relation, called strong behavioral subtyping.

Liskov Substitution Principle (LSP) 下,子类型关系不是由具体实现决定的,而是由 约定的属性和契约 决定的。在具体实现不变时,通过改变约定的属性和契约,就可以改变 subtyping 关系。

In Code

到具体实现上,有些要注意的地方(传参、type-casting, etc.)

Let $S$ and $T$ be two types. We say that $T$ is a subtype of $S$ if a piece of code written for variables of type $S$ can also safely be used on variables of type $T$ .

-CS2030S Unit 2 Lecture Note

这里的 “written for”, “safely be used on” 定义太模糊了。不如 ChatGPT:

Java 或任何面向对象语言里讨论 subtyping(子类型关系) 时,重点在于 类型的抽象属性,而不是具体的代码实现。换句话说,子类型关系关注的是:

  1. 值域(可能的取值集合)

  2. 允许的操作(能对该类型安全地执行哪些操作)

  3. 接口契约(约定行为,方法签名和返回类型)

它并不考虑具体方法内部是怎么实现的,也不看成员变量的实际存储方式或算法逻辑。

比如:

class Animal { void eat() {} }
class Dog extends Animal { void eat() {} }

subtyping 的角度看,Dog <: Animal,因为任何操作可以安全地应用于 Animal,也可以安全地用于 Dog。你不需要关心 Dog.eat() 具体做了什么,只要类型接口满足要求即可。

可以把它理解成 “类型是一种抽象契约,而不是实现细节”

具体地说,

你为父类型写的代码可以在子类型的实例上运行,而不会引起类型错误(从代码运行的角度)或违反类型契约(从抽象属性的角度)

总结

Subtyping relationship 主要还是一个抽象概念。Semantic(语义的) rather than syntactic(语句的).