
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. 會繞過型別檢查立即把該值用作其他任何型別的值
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/542027.html
標籤:其他
上一篇:(Java)設計模式:結構型
