TypeScript 學習(三)

挖坑埋神經病發表於2018-10-18

倉庫地址:github.com/YaliixxG/Ty…

  1. 引用類的成員時,需要加this
  2. 我們使用 new 構造了 Greeter 類的一個例項。 它會呼叫之前定義的建構函式,建立一個 Greeter 型別的新物件,並執行建構函式初始化它。 示例:
class Greeter {
  //屬性
  greeting: string

  //建構函式
  constructor(message: string) {
    this.greeting = message
  }

  //方法
  greet() {
    return "Hello," + this.greeting
  }
}

let greeter = new Greeter("world")
複製程式碼

簡單的繼承示例:

class Animal {
  move(distanceInMeters: number = 0) {
    console.log(`Animal moved ${distanceInMeters}米`)
  }
}
class Dog extends Animal {
  bark() {
    console.log("wang!wang!")
  }
}
const dog = new Dog()
dog.bark()
dog.move(10)
複製程式碼

複雜一點得繼承示例:

class Animal {
  name: string
  constructor(theName: string) {
    this.name = theName
  }
  move(distanceInMeters: number = 0) {
    console.log(`${this.name} moved ${distanceInMeters}米`)
  }
}

class Snake extends Animal {
  // 子類包含一個建構函式,必須呼叫 super(),它會執行基類的建構函式。在構函式訪問this的屬性之前,一定要呼叫super()。這是TypeScript強制執行的一條重要規則。
  constructor(name: string) {
    super(name)
  }
  move(distanceInMeters = 45) {
    console.log("蛇...")
    super.move(distanceInMeters) //訪問類屬性前,需呼叫super,這裡重寫了從基類繼承來的move方法,使得具有不同的功能
  }
}

class Horse extends Animal {
  constructor(name: string) {
    super(name)
  }
  move(distanceInMeters: number = 35) {
    console.log("馬...")
    super.move(distanceInMeters)
  }
}

let sam = new Snake("sammy the Python")
let tom: Animal = new Horse("Tommy the Palomino")

sam.move()
tom.move(34) //這裡tom宣告使Animal型別,但是值為Horse,呼叫tom.move時,會呼叫Horse裡重寫的方法

//輸出:
// 蛇...
// Sammy the Python moved 5m.
// 馬...
// Tommy the Palomino moved 34m.
複製程式碼

靜態屬性

建立類的靜態成員,這些屬性存在於類本身上面而不是類的例項上。
static定義靜態屬性,如果要訪問靜態屬性的話,前面必須加上類名(與訪問例項屬性上加this一樣)

class Grid {
  static orgin = { x: 0, y: 0 } // static定義orgin這個靜態屬性
  abc:(point:{x:number,y:number}){
    //這裡訪問靜態屬性時,在屬性前加上類名的字首
    let xDist = (point.x - Grid.origin.x)
    let yDist = (point.y - Grid.origin.y)
    return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale
  }
  constructor(public scale: number) //這裡建構函式裡面是定義的例項引數,用到例項屬性的時候,前面是加 this 的字首
}

let grid1 = new Grid(1.0);  // 1x scale
let grid2 = new Grid(5.0);  // 5x scale

console.log(grid1.abc({x: 10, y: 10}));
console.log(grid2.abc({x: 10, y: 10}));
複製程式碼

抽象類

  1. 關鍵字 abstract 定義抽象類和在抽象類內部定義抽象方法
  2. 抽象類中的方法,不包含具體實現,只能在派生類(子類)實現
  3. 抽象類定義方法和介面類似,只定義方法簽名,不包含具體方法體
  4. 抽象方法必須包含 abstract 關鍵字並且可以包含訪問修飾符
  5. 抽象類做為其它派生類的基類使用。 它們一般不會直接被例項化,直接例項化會報錯
abstract class A {
  constructor(public name: string) {}

  //普通定義方法,包括具體實現,訪問例項屬性用this
  printName(): void {
    console.log("名字:" + this.name)
  }

  //抽象類方法,必須有關鍵字 abstract ,並且不包含具體實現,只能在派生類實現
  abstract printMeeting(): void
}

//作為抽象類 A 的派生類 B 登場

class B extends A {
  constructor() {
    //在派生類的建構函式必須呼叫super()
    super("LALALALLALA")
  }

  printMeeting(): void {
    console.log("這是基類A定義的抽象類方法,在派生類B的實現")
  }

  hello(): void {
    console.log("這是沒有在基類A定義的方法,只是派生類B定義的普通方法")
  }
}

let a: A // 允許建立一個抽象型別的引用
a = new A() //報錯!不能建立一個抽象類的例項,直接例項化報錯
a = new B() // 允許對一個抽象子類進行例項化和賦值
a.printName() //這是抽象類 A裡面定義的普通方法
a.printMeeting() //這是呼叫抽象類 A 裡面定義的抽象類方法
a.hello() //報錯! 這個方法抽象類A中並沒有定義,所以引用報錯
複製程式碼

高階技巧

建構函式

class Greeter {
  greeting: string
  constructor(message: string) {
    this.greeting = message
  }
  greet() {
    return "hello," + this.greeting
  }
}
let greeter: Greeter //這樣寫是表明Greeter類的例項的型別是 Greeter
greeter = new Greeter("world")
console.log(greeter.greet())
複製程式碼

把類當做介面使用

類定義會建立兩個東西:類的例項型別和一個建構函式。 因為類可以建立出型別,所以你能夠在允許使用介面的地方使用類。(有點不明白 = =)

class Point {
  x: number
  y: number
}

interface Point3d extends Point {
  z: number
}

let point3d: Point3d = { x: 1, y: 2, z: 3 }
複製程式碼

相關文章