[ts入门04] class

189 阅读1分钟

class的本质

class的本质依然是function

class A{
    name: string;
    constructor(name){
        this.name = name;
    }
    say(){
        console.log(`i am ${this.name}`)
    }
}
a.say(); // i am abc
console.log(`type of A: `, typeof A) // type of A:  function
console.log(`type of a: `, typeof a) // type of a:  object

class的作用

个人理解:代码复用,比如继承,实例化

OOP

面向对象(OOP)的特性:A PIE :抽象 多态 继承 封装

封装(Encapsulation)

  • 隐藏数据操作细节,只暴露对外接口。
  • 外界直接调用接口,但不需要(也不可能)知道细节

继承(Inheritance)

  • 子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性
  • 父类:别名 基类,超类
  • 子类:别名 派生类

多态(Polymorphism)

  • 由继承而产生的不同类,对同一个方法可以有不同的响应。
  • 如 Cat 和 Dog 都继承自 Animal,分别实现自己 eat 方法。
  • 无需了解是 Cat 还是 Dog,就可直接调用 eat 方法,程序会自动判断该如何执行 eat

例子1: class基本使用

class Greeter {
    greeting: string; // 成员变量
    constructor(message: string){ // 构造函数
        this.greeting = message;
    };
    sayHi() { // 成员函数
        console.log(this.greeting);
    }
}

let myGreeter1 = new Greeter('hi, nice to meet you!');
myGreeter1.sayHi(); // hi, nice to meet you!

例子2: class继承

class Animal {
    name: string;
    constructor(name: string){
        this.name = name;
    };
    move(distance: number){
        console.log(`${this.name} moved ${distance} m`);        
    };
};


class Snake extends Animal {
	  // 子类执行父类的构造函数
    constructor(name: string){
        // 注意!! TypeScript强制执行的重要规则
        // 子类构造函数必须调用super方法,之后才能正常使用this, 
        super(name); 
    };
  	// 子类重写了父类的move方法
    move(distance: number = 5){
        console.log('snake slitering...');
        super.move(distance);
    }
}

let snake1 = new Snake('sk1');
snake1.move();   // snake slitering...  sk1 moved 5 m

let snake2: Animal = new Snake('sk2');
snake2.move(100);   // snake slitering... sk2 moved 100 m

例子3: 修饰符public protected private

class Plant {
    // public 子类和实例都可访问
    public nme:string;
    // protected 子类可访问,实例不可访问
    protected age: number;
    // private:子类和实例都不可访问
    private region: string;
    
  	// protected修饰构造函数,意味着Plant不能被实例化
    protected constructor(name:string, age: number, region:string){
        this.name = name;
        this.age = age;
        this.region = region;
    }
};


class Bamboo extends Plant {
    public color: string;
    // public修饰构造函数,意味着Bamboo可以被实例化
    public constructor(name: string, age:number, region:string, color: string){
        super(name, age, region);
        this.color = color;
    }
    public getInfo(){
        console.log(`my name is ${this.name}`);
        console.log(`my age is ${this.age}`);
        // console.log(`my region is ${this.region}`);// compile error!
    }
};


// Plant不可实例化
//  let plant1 = new Plant('tree', 2, 'south'); // compile error!

// Bamboo可实例化
let bamboo1 = new Bamboo('boom1', 1, 'north','lightGreen');


// 不可以访问bamboo1.age和bamboo1.region
console.log(`bamboo1.name=${bamboo1.name}, bamboo1.color=${bamboo1.color}`);  
// 打印:bamboo1.name=boom1, bamboo1.color=lightGreen

修饰器:限制访问

修饰属性或方法

  • public,TypeScript里,成员(包括属性和方法)都默认为 public
  • private,只能当前类内部访问, 子类和实例不能访问
  • protected,可在当前类和子类内部访问, 实例不能直接访问

修饰构造函数(特殊)

  • private ,该类不允许被继承或者实例化
  • protected,该类运行被继承,不允许实例化

例子4: readonly修饰符

class Octopus{
  	// readonly变量初始化(可写):声明时
    public readonly enviroment: string;
    public readonly legs: number = 8;
    public name: string; 
  
    public constructor(enviroment:string, name: string, legs: number){
        // readonly变量初始化(可写):构造函数
        this.enviroment = enviroment;
        this.legs = legs;
        this.name = name;
    }
}

// oct1.enviroment 和 oct1.legs 只能读不能写
// oct1.name 可读可写
let oct1 = new Octopus('water', 'oct1', 10);
console.log(oct1.enviroment, oct1.legs, oct1.name); // water 10 oct1    
oct1.name = 'newOct1'
console.log(oct1.enviroment, oct1.legs, oct1.name);// water 10 newOct1 

例子5 参数属性

class OriginalAnimal{
    private name:string;
  
    public constructor(name: string){
        this.name = name;
    }
  
    getInfo(){
        console.log(`OriginalAnimal: my name is ${this.name}`);
    }
}

let myOrigin1 = new OriginalAnimal('kawa');
myOrigin1.getInfo();// OriginalAnimal: my name is kawa   



class BetterAnimal{
    // 参数属性(修饰词):构造函数的参数中使用修饰词 如public
	  // ts规定此构造函数和OriginalAnimal构造函数是等价的
    constructor(private name:string){}; 
  
    getInfo(){
        console.log(`BetterAnimal: my name is ${this.name}`);      
    }
}

let myBetter1 = new BetterAnimal('loty');
myBetter1.getInfo(); //BetterAnimal: my name is loty

参数属性的作用?

  • 个人理解是ts语法糖
  • 使用参数属性,可以把声明和赋值合并到一起

例子6 静态属性

class Movie{
    public static goal:string = 'for fun!'; // 静态属性
  
    public constructor(public name:string) { };
  
    public getInfo(){
        console.log(`i am movive ${this.name} and my goal is ${Movie.goal}`);
    }
};

let myMovie = new Movie('matrix');
// 类的内部方法getInfo访问静态属性
myMovie.getInfo();  // i am movive matrix and my goal is for fun!

// 类的外部直接访问静态属性 
console.log(`静态属性Movie.goal: ${Movie.goal}`); // 静态属性Movie.goal: for fun!

静态属性

  • static关键字声明
  • 属于类,不属于实例
  • 可以通过类名.静态属性来访问