TS学习第三节(类)

132 阅读1分钟

 ts官网搬运工

使用类的例子:

class Greeter{
    greeting: string;
    constructor(message: string){
        this.greeting = message;
    }
    greet(){
        return 'hello, ' + this.greeting;
    }
}

继承

class Animal{
    move(distanceInMeters: number = 0){
        console.log(`Animal moved ${ distanceInMeters }`)
    }
}
class Dog extends Animal{
    bark(){
        console.log('Woof! Woof!!!')
    }
}
const dog = new Dog();
dog.brak();
dog.move(10);
dog.brak();

类从基类中继承属性和方法。这里的Dog是一个派生类,它派生自Animal基类,通过extends关键字。派生类通常被称作子类,基类通常被称为超类。

class Animal{
    name: string;
    constructor(theName: string){ this.name = theName }
    move(distanceInMeters: number = 0){
        console.log(`${ this.name } moved ${ distanceInMeters }m`)
    }
}
class Snake extends Animal{
    constructor(name: string){ super(name) }
    move(distanceInMeters = 5){
        console.log("slithering...");
        super.move(distanceInMeters);
    }
}
class Horse extends Animal{
    constructor(name: string){ super(name) }
    move(distanceInMeters = 45){
        console.log("Galloping...");
        super.move(distanceInMeters);
    }
}
let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);

与前一个例子不同的是,派生类包含了一个构造函数,它必须调用super(), 它会执行基类的构造函数。而且在构造函数里访问this的属性之前,我们一定要调用super()。这是TypeScript强制执行的一条重要规定。

公共,私有与受保护的修饰符

默认public

使用public重写Animal

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

理解private

当成员被标记为private时,他就不能再类外面访问了。

class Animal{
    private name: string;
    constructor(theName: string){ this.name = theName}
}
new Animal('Cat').name; //error

TypeScript使用的是结构类型系统。

class Animal{
    private name: string;
    constructor(theName: string){ this.name = theName}
}
class Rhino extends Animal{
    constructor(){ super('Rhino') }
}
class Employee{
    private name: string;
    constructor(theName: string){ this.name = theName }
}
let animal = new Animal('Goat');
let rhino = new Rhino();
let employee = new Employee('Bob');

animal = rhino;
animal = employee; //error;

理解protected

protected修饰符与private修饰符的行为很相似,但有一点不同,protected成员在派生类中任然可以访问。

class Person{
    protected name: string;
    constructor(name: string){ this.name = name }
}
class Employee extends Person{
    private department: string;
    constructor(name: string, department: string){
        super(name);
        this.department = department;
    }
    public getElevatorPitch(){
        return `Hello, my name is ${ this.name } and I work in ${ this.department }.`
    }
}
let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); //error

注意:我们不能再Person外使用name,但可以在它的派生类中重写name;

构造函数也可以被标记为protected。意味着这个类不能在包含它的类外部实例化,但是可以被继承。

class Person{
    protected name: string;
    protected constructor(theName: string){ this.name = theName }
}
class Employee extends Person{
    private department: string;
    constructor(name: string, department: string){
        super(name);
        this.department = department;
    }
    public getElevatorPitch(){
        return `Hello, my name is ${ this.name } and I work in ${ this.department }.`
    }
}
let howard = new Employee("Howard", "Sales");
let john = new Person("John"); //error

readonly修饰符

可以使用readonly关键字将属性设置为只读。只读属性必须在声明或构造函数里被初始化。

class Octopus{
    readonly name: string;
    readonly numberOfLegs: number = 8;
    constructor (theName: string){
        this.name = theName;
    }
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man"; //error;

存取器

TypeScript支持通过getters/setters来截取对象成员的访问。

letpasscod = "secret passcod";
class Employee{
    private _fullName: string;
    get fullName(): string{
        return this._fullName;
    }
    set fullName(newName: string){
        if(passcode && passcode == 'secret passcod'){
            this._fullName = newName;
        }else{
            console.log("Error: Unauthorized update of employee!");
        }
    }
}
let employee = new Employee();
employee.fullName = "Bob smith";
if(employee.fullName){
    alert(employee.fullName);
}