Class(類)分享 第四節
阿新 • • 發佈:2020-11-26
一、基礎
// es6 普通的一個類 // 建構函式為例項新增成員,類的所有方法都定義在類的prototype屬性,即原型上面。 class Animal { name constructor(name, age){ this.name = name } move(distance){ console.log(`The speed of ${this.name} is ${distance}m/s`) } } let a = new Animal("Tom") console.log(a.move(5)) //ts, 成員,引數,函式返回值加上型別檢查,例項加上類型別 class Animal { // 聲明瞭類的例項的型別 name: string constructor(name: string){ this.name = name } move(distance: number): void{ console.log(`The speed of ${this.name} is ${distance}m/s`) } } let a: Animal = new Animal("Tom") console.log(a.move(5))
二、繼承
使用extends
關鍵字實現繼承。子類中如果有構造方法,必須使用super
關鍵字來呼叫父類的建構函式
class Animal { name: string; age: number; constructor(name: string, age: number) { this.name = name this.age = age } move(distance: number): void { console.log(`The speed of ${this.name} is ${distance}m/s`) } } class Cat extends Animal { catkind // 子類有建構函式,必須使用super呼叫父類構造方法 constructor(name: string, age: number, catkind: string) { super(name, age) this.catkind = catkind } // 重寫move move(distance: number): void { console.log("cat walking..."); super.move(distance) } } class Dog extends Animal { dogkind constructor(name: string, age: number, dogkind: string) { super(name, age) this.dogkind = dogkind } move(distance: number): void { console.log("dog walking..."); super.move(distance) } } let cat1: Cat = new Cat("Tom", 5, "persian") console.log(`${cat1.name} is ${cat1.age} years old,its kind is ${cat1.catkind} cat`) console.log(cat1.move(5)) let dog1: Dog = new Dog("jack", 3, "Husky") console.log(`${dog1.name} is ${dog1.age} years old,its kind is ${dog1.dogkind} dog`) console.log(dog1.move(10))
三、public private 和 protected
- public:預設所有的成員和方法都是public。修飾的成員和方法是公開的,可以在任何地方被訪問到
- private: 修飾的成員和方法是私有的的,只能在宣告它的類的內部被訪問, 不允許被例項和子類訪問
- protected:修飾的成員和方法是受保護的,只能在宣告它的類和子類的內部被訪問, 不允許被例項訪問
// 1. public class Animal { public name: string; public constructor(name: string) { this.name = name; } public move(distance: number): void { console.log(`The speed of ${this.name} is ${distance}m/s。`) } } let cat1 = new Animal("Tom") console.log(cat1.name) console.log(cat1.move(5)) // 2.1 private-成員 class Animal { private name: string; public constructor(name: string) { this.name = name; } public move(distance: number): void { console.log(`The speed of ${this.name} is ${distance}m/s。`) } } let cat1 = new Animal('Tom'); console.log(cat1); console.log(cat1.name); // error 例項不能訪問 console.log(cat1.move(85)); // 類內部可以訪問 class Cat extends Animal{ public constructor(name: string){ super(name); } public say() { console.log(`${this.name} say miao~miao~`); } } let cat2 = new Cat('haha'); console.log(cat2.name) // error 在子類的例項中也不能被訪問 // 2.2 private-建構函式 // 建構函式修飾為 private 時,該類不允許被繼承或者例項化 class Animal { public name; private constructor(name) { this.name = name; } } class Cat extends Animal { // error a. 不能被繼承 constructor(name) { super(name); } } let cat1 = new Animal('Jack'); // error b. 不能被例項化 // 3.1 protected-成員 class Animal { protected name: string; public constructor(name: string) { this.name = name; } public move(distance: number): void { console.log(`The speed of ${this.name} is ${distance}m/s。`) } } let cat1 = new Animal('Tom'); console.log(cat1.move(85)); // 類內部可以訪問 console.log(cat1.name); // error 例項不能訪問 class Cat extends Animal{ public constructor(name: string){ super(name); } public say() { console.log(`${this.name} say miao~miao~`); // 在子類中可以訪問 } } let cat2 = new Cat('haha'); console.log(cat2.say()) console.log(cat2.name) // error 在子類的例項中也不能被訪問 // 3.2 protected-建構函式 // 建構函式修飾為 protected 時,該類只允許被繼承 class Animal { public name; protected constructor(name) { this.name = name; } } class Cat extends Animal { constructor(name) { super(name); } } let a = new Animal('Jack'); // error 不能被例項化
四、readonly
使用readonly
關鍵字將成員設定為只讀的。 只讀成員必須在宣告時或建構函式裡被初始化。
class Animal {
readonly name: string;
readonly age: number = 18; // 宣告時初始化
public constructor(name: string) {
this.name = name; // 建構函式裡初始化
}
}
let a = new Animal('Jack');
console.log(a.name); // Jack
a.name = 'Tom'; // error 只讀
注意如果readonly
和其他訪問修飾符同時存在的話,需要寫在其後面。
class Animal {
public readonly name: string;
public constructor(name: string) {
this.name = name;
}
}
五、引數屬性
一般,我們先宣告類的成員和建構函式內賦值。通過引數屬性,我們將宣告和賦值合併起來。
// 一般
class Animal {
public name: string;
public constructor(name: string) {
this.name = name;
}
}
let a = new Animal('Jack');
console.log(a.name); // Jack
// 引數屬性
class Animal {
// public name: string; // 省略
public constructor(public name: string) {
// 引數屬性,必須有修飾符 public,protected,private或readonly
// this.name = name; // 可省略
}
}
let a = new Animal('Jack');
console.log(a.name); // Jack
六、存取器
使用 getter 和 setter 可以改變屬性的賦值和讀取行為。當類成員上定義存取器時,就不能使用正常成員宣告
class Animal {
// name: string 成員宣告
constructor(name: string) {
this.name = name;
}
get name() { // 存取器
return 'Jack';
}
set name(value) {
console.log('setter: ' + value);
}
}
let a = new Animal('Kitty');
a.name = 'Tom';
console.log(a.name);
七、靜態屬性
可以通過static定義建立類的靜態成員和方法,這些成員和方法存在於類的本身而不是類的例項上。只能通過類名訪問,不能被建構函式例項化
class Animal {
static firstWord = "hello";
constructor(public name: string){}
sayHi(){
console.log(Animal.firstWord)
}
static isAnimal(animal: Animal): void {
console.log(animal instanceof Animal);
}
}
let a = new Animal("Tom")
console.log(Animal.firstWord)
Animal.isAnimal(a)
console.log(a.firstWord) // error, 例項不能訪問
a.isAnimal(a) // error
a.sayHi()
八、抽象類
abstract
用於定義抽象類和其中的抽象方法。顧名思義,抽象類和抽象方法是對對一些物件的屬性和行為進行高度抽象,一般不包含具體實現細節,所以基類使用。所以,抽象類是不允許被例項化的。其次,抽象類中的抽象方法必須被子類實現,因為一般不包含實現細節。
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
abstract move(distance: number): void;
}
class Cat extends Animal {
constructor(name: string) {
super(name)
}
move(distance: number): void { // 必須實現基類的抽象方法
console.log(`The speed of ${this.name} is ${distance}m/s`)
}
}
let a = new Animal('Jack'); // error,不允許例項化
let cat = new Cat('Tom');
cat.move(5)
九、類和介面
一般來講,一個類只能繼承自另一個類,有時候不同類之間可以有一些共有的屬性和行為,這時候就可以把這些通用屬性和方法提取成介面(interfaces),用implements
關鍵字來實現。
舉例,門是一個類,防盜門是它的子類。車也是一個類,車和防盜門都有報警功能,將其提取成一個報警方法。作為一個介面,防盜門和車等都可以實現它。
interface Alarm {
alert(): void;
}
class Door {
}
class SecurityDoor extends Door implements Alarm {
alert() {
console.log('SecurityDoor alert');
}
}
class Car implements Alarm {
alert() {
console.log('Car alert');
}
}
一個類只能繼承自一個類,但也可以實現多個介面
interface Alarm { // 報警
alert(): void;
}
interface controlDoor { // 開關門
openDoor(): void;
closeDoor(): void;
}
class Car implements Alarm, controlDoor {
alert() {
console.log('Car alert');
}
openDoor() {
console.log('Car door open');
}
closeDoor() {
console.log('Car door close');
}
}
類定義會建立兩個東西:類的例項型別和一個建構函式。 因為類可以創建出型別,所以你能夠在允許使用介面的地方使用類。
class Point {
x: number;
y: number;
}
interface Point3d extends Point { // 類可以被當作介面使用
z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};