TS中的类

类的基本结构

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

let greeter = new Greeter("world");

如上声明一个 Greeter类。这个类有3个成员:一个叫做 greeting的属性,一个构造函数和一个 greet方法。

最后一行,使用 new构造了 Greeter类的一个实例。 它会调用之前定义的构造函数,创建一个 Greeter类型的新对象,并执行构造函数初始化它。

继承

class A {
  move(num:number=0){
    console.log(num);  
  }
}
class B extends A{
  back(){
    console.log('123');
    
  }
}
const b = new B()
b.back()//123
b.move(10)//10

类从基类中继承了属性和方法。 这里, B是一个 派生类,它派生自 A 基类,通过 extends关键字。 派生类通常被称作 子类,基类通常被称作 超类/父类

重写

class A {
  name:string;
  constructor(theName:string) {
    this.name = theName 
  }
  move(num:number=0){
    console.log(`${this.name}${num}`);
  }
}
class B extends A{
  constructor(name:string){
    super(name)
  }
  move(num=5){
    super.move(num)
    
  }
}
class C extends A{
  constructor(name:string){
    super(name)
  }
  move(num=6){
    super.move(num)
    
  }
}
let b = new B('alibaba')
let c:A = new C('baidu')
b.move() 
c.move(123)

输出

alibaba5
baidu123

简单来讲,我们创建了两个A的子类,B和C,B和C都重写了A中的move方法,使得 move方法根据不同的类而具有不同的功能。

注意,即使 c被声明为 A类型,但因为它的值是 C,调用 c.move(34)时,它会调用 C里重写的方法

与前一个例子的不同点是,子类中要执行父类的构造函数必须在子类的构造函数中执行super()。 而且,在构造函数里访问 this的属性之前,我们 一定要调用 super()。 这个是TypeScript强制执行的一条重要规则。

公共修饰符(public)

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

成员都为可见,且能被修改

私有修饰符(private)

在父类外面无法被访问

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

new Animal("Cat").name; // 错误: 'name' 是私有的.

受保护的修饰符(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); // 错误,属性“name”受保护,只能在类“Person”及其子类中访问

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

class Person {
    protected name: string;
    protected constructor(theName: string) { this.name = theName; }
}

// Employee 能够继承 Person
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"); // 错误: 'Person' 的构造函数是被保护的.

只读修饰符(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 with the 3-piece suit"; // 错误! name 是只读的.

存取器

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

这是一个简单类

静态成员(static)

静态属性和方法

class A{
  static name:String = 'baidu'
  age : number = 20;

  static readyName (){
    console.log('静态方法');   
  }
  readyAge(){
    console.log('实例方法');
    
  }
}
A.name
A.age // 类型“typeof A”上不存在属性“age”
let a = new A()
a.readyName() // 属性“readyName”在类型“A”上不存在
a.readyAge()

静态属性和方法只存在与类的本身,外部无法调用

实例属性和方法只能通过类的实例来调用

抽象类(abstract)

举一个例子,飞机大战,面有好多飞机有敌方的飞机玩家飞机等。那么根据类的划分,我们可以划分敌方飞机类玩家飞机类,但是我们从继承的角度仔细想一想,是不是有一些公共的部分,例如,飞机的名字飞机的生命值飞机的速度攻击等一系列公共的属性和方法

我们先看一个普通类实现

class Plane{
  name:string = '';
  life:string = '';

  attack(){
    console.log(`{this.name}飞机正在攻击`)
  }
}

class PlayerPlane extends Plane{
  name:string = '玩家1';
  life:string = '100';
  // ...
   attack(){
    console.log(`{this.name}飞机正在攻击`);
    // 飞机相同的逻辑1
    // 飞机相同的逻辑2
    // 飞机的不同逻辑

  }
}

class EnemyPlane extends Plane{
  name:string = '小罗罗1';
  life:string = '10';
  // ...
   attack(){
    console.log(`{this.name}飞机正在攻击`)
    // 飞机相同的逻辑1
    // 飞机相同的逻辑2
    // 飞机的不同逻辑
  }
}

我们创建了一个类,里面有属性和方法,把它当做飞机的模板

然后开始造飞机,每个飞机都有自己的属性和方法

可以看出,有些相同的逻辑每个子类都要写一遍

为了避免这个问题,我们可以用抽象类

abstract class Plane{
  abstract name:string ;
  abstract life:string ;

  attack(){
    console.log(`{this.name}飞机正在攻击`)
    // 飞机相同的逻辑1
    // 飞机相同的逻辑2
    this.otherFunction();
  }
  // 飞机的不同逻辑
  abstract otherFunction()
}

class PlayerPlane extends Plane{
  name:string = '玩家1';
  life:string = '100';
  // ...
  otherFunction(){
    // ...个性化
  }
}

class EnemyPlane extends Plane{
  name:string = '小罗罗1';
  life:string = '10';
  // ...
  otherFunction(){
    // ...个性化
  }
}

把所有相同的逻辑放到父类中去实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值