[TOC]
>[success] # 其他語言 interface 接口
[第一條的參考文章](https://blog.csdn.net/qq_21033779/article/details/79071887)
~~~
1.了解什么是接口:接口只是定義了一些方法,而沒有去實現,多用于程序
設計時,只是設計需要有什么樣的功能,但是并沒有實現任何功能,這些功
能需要被另一個類(B)繼承后,由 類B去實現其中的某個功能或全部功能
'接口定義了多個類的公共行為規范,這些行為是和外部進行交流的通道'
2.瘋狂java 講義中描述接口(這里筆者稍微改動了下):電腦主板上有usb接
口,但是不同時期usb接口遵循不同的協議,必須遵循了這個協議才能享受
對應不同時期usb 版本帶來的體驗,這個規范我們可以理解成接口,他定義
了一些規則,但具體的方法我們實現這個接口的時候各大廠商按照自己優化
去實現,好處是讓規范和實現分離,讓軟件之間面向接口耦合,是一種松耦
合的設計,這樣主板就不會關心這個是那個廠家制造的usb,也不管你的內
部實現,只要你遵循了我的協議,我們就能匹配。'java' 還利用接口的特性
實現了多繼承
3.pyhon 角度來看,pyhon沒有明確接口概念,使用的抽象類來變相實現,
加上本身的多繼承的特性,也讓他可以將接口這個概念和其他語言劃分開
4.上面是通過csdn作者--' leeyan85'和瘋狂java講義書中加上筆者本身略微
學習過pyhon 和 java,在這基礎上通過語言的對比,和描述希望可以對前端
本身沒有接口概念的開發一點幫助
~~~
>[success] # TS -- 接口
通過案例來看ts 中的接口
~~~
function printPersonInfo(paramsInfo: { name: string; sex: string }) {
console.log(`姓名:${paramsInfo.name}性別:${paramsInfo.sex}`)
}
let paramsInfo = { name: 'wang', age: 12, sex: '男' }
printPersonInfo(paramsInfo) // 姓名:wang性別:男
// 錯誤使用因為沒有使用定義的sex
// let paramsInfo = {name:'wang',age:12}
// printPersonInfo(paramsInfo) // 報錯 錯誤使用因為沒有使用定義的sex
~~~
~~~
1.雖然實現了,和傳遞參數,缺點靈活性不高,如果在遇到相同類似的結構,不能將公共格式參數的提取出來復用,這種情況下
就可以使用'接口'
~~~
>[info] ## 接口定義
~~~
1.TypeScript 對對象的類型檢測遵循一種被稱之為“鴨子類型”(duck typing)或者“結構化類型(structural subtyping)”的準則,
即只要兩個對象的結構一致,屬性和方法的類型一致,則它們的類型就是一致的。
2.接口的作用就是為這些類型命名和為你的代碼或第三方代碼定義契約
~~~
>[danger] ##### 了解接口 -- interface
~~~
1. 使用在變量前聲明'interface'
2. 簡單案例:
聲明一個interface:
interface person {
name: string;
age: number;
}
然后就可以使用這個interface來限制一個對象的類型:
let tom: person = {
name: 'tom',
age: 12
}
3.和剛才比我們解決了缺點中的問題可以公共提取,規范一個系列
~~~
* 所有動物都有一個最基本的信息名字和性別,必須按照這個規范來創建
~~~
interface Baseinfo {
name:string,
sex:string
}
// 人
function printPesonInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }性別:${parmasinfo.sex}`)
}
// 動物
function printAnimalInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }性別:${parmasinfo.sex}`)
}
let paramsinfo = {name:'wang',age:12,sex:'男'}
printPesonInfo(paramsinfo) // 姓名:wang性別:男
let paramsAnimainfo = {name:'小黑',age:12,sex:'公'}
printAnimalInfo(paramsAnimainfo) // 姓名:小黑性別:公
~~~
>[danger] ##### 可選類型 -- 用'?'號修飾
~~~
1.現在我們發現不是接口中提供的每一個參數我們都需要,為此'TS' 提供了
一種'?' 來修飾,被問號修飾的參數就是可以選傳,不是必須參數
~~~
~~~
interface Baseinfo {
name:string,
sex?:string
}
// 人
function printPesonInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }`)
}
let paramsinfo = {name:'wang'}
printPesonInfo(paramsinfo) // 姓名:wang
~~~
>[danger] ##### 索引簽名 -- 可以添加不確定參數
~~~
1.剛才的問號讓我們可以選填一些參數,但是如果需要增加一些不確定
參數就需要使用 '索引簽名'
2.利用這個可以規定你的索引簽名的類型(即使你的索引規定是string類型
但也可以使用數字,案例二有說明)
3.主要注意這里有個問題:需要注意的是,一旦定義了任意屬性,
那么'確定屬性和可選屬性的類型都必須是它的類型的子集'(案例三)
~~~
* 案例一
~~~
interface Baseinfo {
name:string,
sex?:string,
[other:string]:any //可以叫任意名字這里叫other 你也可叫aaaa
}
// 人
function printPesonInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }`)
}
// 接口中的索引簽名other 就會收到age
printPesonInfo( {name:'wang',age:13}) // wang
~~~
* 案例二的錯誤示范
~~~
interface Person {
name: string;
age?: number;
[propName: string]: any;
}
let tom: Person = {
name: 'Tom',
age: 25,
1: 'male' // 因為key 會調用 自帶的toString 方法
};
~~~
* 案例三
~~~
// 錯誤示范
// age 和name 必須是 任意屬性的子集
interface Person {
name: string
age?: number // 報錯
[propName: string]: string // 改正 [propName: string]: any; 或者 [propName: string]: string|number
}
~~~
* 最優方法
http://www.hmoore.net/book/cyyspring/tyscript/preview/ts--%E7%B1%BB%E5%9E%8B%E7%BC%A9%E5%87%8F.md
>[danger] ##### 限制接口中的參數是只讀 -- readonly
~~~
1.readonly 和 const 都是只讀,但兩者如何用區別在哪里,首先'readonly '
是'TS' 在接口提出,只針對接口中的參數賦值后就禁止更改,而const 是
es6 提出的針對變量,不讓變量進行更改
2.用'ts' 文檔的總結來說:最簡單判斷該用readonly還是const的方法是看要
把它做為變量使用還是做為一個屬性。 做為變量使用的話用const,若做
為屬性則使用readonly。
~~~
* 使用
~~~
interface Point {
readonly x: number;
readonly y: number;
}
// p1 是接口Point 類型
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error! 已經設置了readonly 屬性所以禁止更改
~~~
>[danger] ##### 接口 數組 和只讀
~~~
1.我們還可以利用接口定義數組位置的類型,和元組不同,元組不僅限制
了類型也限制了最開始賦值時候的長度(push 還是可以往元組添加東西的)
~~~
* 接口定義數組
~~~
// 接口 數組 和只讀
// 定義了一個數組接口,數組第一位必須數字,第二位是字符串
interface ArrInter {
0:number,
1:string
}
let arr: ArrInter = [1,"w",3]
console.log(arr)
~~~
* 接口 數組 和只讀
~~~
// 定義了一個數組接口,數組第一位必須數字,第二位是字符串
interface ArrInter {
readonly 0:number,
1:string
}
let arr: ArrInter = [1,"w",3]
arr[0] = 5 // erro 后續禁止改變
~~~
>[danger] ##### 接口定義函數
~~~
1.接口不止能定義變量值也可以定義函數
~~~
* 將BaseInfo 加工
~~~
// 定義了一個信息接口,里面有姓名,年齡和一個吃的方法返回的類型是string類型
interface BaseInfo{
name:string,
age:number,
eat(food: string):string
}
const personInfo:BaseInfo = {
name:'wang',
age:99,
eat(parmas){
return parmas
}
}
~~~
* 只定義 方法的接口
~~~
1.對于函數類型的類型檢查來說,函數的參數名不需要與接口里定義的名字相匹配
2.函數的參數會逐個進行檢查,要求對應位置上的參數類型是兼容的
~~~
~~~
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(src: string, sub: string): boolean {
let result = src.search(sub);
return result > -1;
}
~~~
* 類型別名
~~~
// ts箭頭函數不加大括號的含義是 返回 類型
type PersonInfo = (name:string) => string
// 這里箭頭函數是正常的js 表達的意思
let personName:PersonInfo = (name) => name
// 做一個小備注冒號后面等號前面屬于ts定義, (x: number, y: number, z?:number) => number
// 是ts的定義這里=> 不是js箭頭函數
const add2: (x: number, y: number, z?:number) => number = add
~~~
>[danger] ##### 接口做閉包(混合類型)
~~~
1.利用function 也可以定義key的方式
~~~
* 有時候,一個函數還可以有自己的屬性和方法:
~~~
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) { };
counter.interval = 123;
counter.reset = function () { };
return counter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
~~~
* 編譯后效果
~~~
function getCounter() {
var counter = function (start) { };
counter.interval = 123;
counter.reset = function () { };
return counter;
}
var c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
~~~
* 案例二 編譯前
~~~
interface Counter {
(): void;
count: number;
}
function getCounter(): Counter {
const c = ()=>{
c.count++
}
c.count = 0
return c
}
~~~
* 編譯后
~~~
function getCounter() {
var c = function () {
c.count++;
};
c.count = 0;
return c;
}
~~~
>[danger] ##### 繼承接口
~~~
1.接口類型可以繼承和被繼承,比如我們可以使用如下所示的 extends 關鍵字實現接口的繼承。
~~~
~~~
interface DynamicLanguage {
rank: number // 定義新屬性
}
interface TypeSafeLanguage {
typeChecker: string // 定義新的屬性
}
/** 繼承多個 */
interface TypeScriptLanguage extends DynamicLanguage, TypeSafeLanguage {
name: 'TypeScript'
}
~~~
* 我們僅能使用兼容的類型覆蓋繼承的屬性
~~~
{
interface DynamicLanguage {
rank: number // 定義新屬性
}
interface TypeSafeLanguage {
typeChecker: string // 定義新的屬性
}
/** 繼承多個 */
interface TypeScriptLanguage extends DynamicLanguage, TypeSafeLanguage {
name: 'TypeScript'
}
/** ts(6196) 錯誤的繼承,name 屬性不兼容 */
interface WrongTypeLanguage extends TypeScriptLanguage {
typeChecker: number; // typeChecker: string; 可以的
}
}
~~~
- TypeSprict -- 了解
- TS-- 搭建(一)webpack版本
- TS -- 搭建(二)直接使用
- TS -- 基本類型
- ts -- 類型推導和字面量類型
- ts -- 類型擴展和類型縮小
- ts -- any場景
- ts -- 使用unknown 還是 any
- ts -- any/never/unknown
- ts -- 斷言
- ts -- 類型大小寫疑惑
- ts -- 數組類型 [] 還是泛型疑惑
- TS -- 枚舉
- 外部枚舉
- TS -- 函數
- ts -- 重載作用
- ts -- 05 this is
- 解構
- TS -- 接口
- 繞過接口的多余參數檢查
- Interface 與 Type 的區別
- TS -- 類
- ts -- 類作為類型
- TS -- 交叉和聯合 類型
- ts -- 交叉類型
- ts -- 聯合類型
- ts -- 交叉和聯合優先級
- ts -- 類型縮減
- TS -- 什么是泛型
- ts -- 泛型函數表達式/函數別名/接口
- ts -- 泛型類
- ts -- extends 泛型約束
- ts -- 泛型new
- ts -- Ts的泛型
- TS -- 縮小類型詳解類型守衛
- TS -- 類型兼容性
- TS -- 命名空間與模塊化
- ts -- 模塊化
- ts -- 命名空間
- TS -- 工具方法
- Record -- 一組屬性 K(類型 T)
- Exclude -- 從聯合類型中去除指定的類
- Extract -- 聯合類型交集
- NonNullable -- 從聯合類型中去除 null 或者 undefined
- Partial -- 將所有屬性變為可選
- Required -- 所有屬性變為必填
- Readonly -- 所有屬性只讀
- Pick -- 類型中選取出指定的鍵值
- Omit -- 去除指定的鍵值