读编程与类型系统笔记07_子类型(子类定义)
zazugpt 2024-09-09 10:33:53 编程文章 22 ℃ 0 评论
1.子类型
1.1.在期望类型T的实例的任何地方,都可以安全地使用类型S的实例,则类型S是类型T的子类型
1.1.1.里氏替换原则(Liskov substitution principle)
2.名义子类型
2.1.明确指定
2.2.显式声明一个类型是另一个类型的子类型
2.3.大部分主流编程语言采用的方式
2.3.1.Java
2.3.2.C#
2.4.TypeScript通过使用unique symbol可以模拟名义子类型
3.结构子类型
3.1.类型具有相同的结构
3.2.不需要显式声明子类型关系
3.3.一个类型的结构与另一个类型相似(具有相同的成员,可能还有额外的成员),自动被视为后者的子类型
3.4.TypeScript使用结构子类型
3.5.即使类型不在我们的控制范围内,我们在类型之间仍然能建立关系
3.5.1.例如:我们不能修改的来自外部库的一个类型
4.极端情况
4.1.顶层类型
4.1.1.把任何东西赋值给它的类型
4.1.1.1.用来存储任何东西
4.1.1.2.C#的Object
4.1.1.3.TypeScript的unknown
4.1.1.3.1.null的类型是null
4.1.1.3.2.undefined的类型是undefined
4.1.1.3.3.Object
4.1.1.3.4.三者和类型即unknown
4.1.1.3.4.1.Object | null |undefined
4.1.1.3.5.只有当我们确认一个值具有某个类型时,才能把该值用作该类型
4.1.1.3.5.1.C#提供了is关键字
4.1.1.3.5.2.Java则提供了instanceof
4.1.2.其他任何类型的父类型
4.1.3.位于子类型层次结构的顶端
4.2.底层类型
4.2.1.可以赋值给任何东西的类型
4.2.1.1.没有某种类型的实例可用
4.2.1.2.TypeScript的never
4.2.2.其他任何类型的子类型
4.2.3.位于子类型层次结构的底端
4.2.4.始终是一个空类型:这是我们不能为其创建实际值的类型
4.2.5.允许我们假装有任何类型的一个值,即使我们并不能生成这个值
4.2.6.很少有主流语言提供底层类型
4.2.6.1.使一个类型成为空类型,但不能使其成为底层类型
4.2.6.2.除非在编译器中实现,否则我们无法自定义底层类型
5.和类型
5.1.父类型比子类型的类型更多
5.1.1.例如:Triangle | Square是Triangle | Square | Circle的子类型
5.2.Variant能够封装几个类型中某个类型的值,但是它本身不是其中任何一个类型
6.可变性
6.1.协变性
6.1.1.一个类型保留其底层类型的子类型关系
6.1.2.数组具有协变性,因为它保留了子类型关系
6.1.3.当处理集合(如LinkedList)时,不同的语言具有不同的行为
6.1.3.1.在C#中,必须通过声明接口并使用out关键字(ILinkedList),显式指出一个类型(如LinkedList)的协变
6.1.4.函数的返回类型具有协变性
6.2.逆变性
6.2.1.一个类型颠倒了其底层类型的子类型关系
6.2.2.大部分编程语言中,函数的实参是逆变的
6.2.2.1.TypeScript是一个例外
6.2.2.1.1.故意做出的设计决策
6.3.双变性
6.3.1.类型的底层类型的子类型关系决定了它们互为子类型
6.3.2.在TypeScript中函数实参的双变性可能导致错误的代码通过编译
6.4.不变性
6.4.1.一个类型不考虑其底层类型的子类型关系
6.4.2.C#中的List具有不变性
7.any类型
7.1.可以把任何值赋值给any
7.2.可以把any值绕过类型检查赋值给其他任何类型
7.3.会绕过类型检查立即把该值用作其他任何类型的值
本文暂时没有评论,来添加一个吧(●'◡'●)