TypeScript学习摘要(三)——类

修饰符

public

  • 在TypeScript里,成员都默认为 public

private

  • 当成员被标记成 private时,只能在声明它的类的内部访问

    class Animal {
        private name: string;
        constructor(theName: string) { this.name = theName; }
    }
    
    new Animal("Cat").name; // 错误: 'name' 是私有的.
    
  • 当我们比较带有 privateprotected成员的类型的时候,如果其中一个类型里包含一个 private/protected成员,那么另外一个类型中也必须存在这样一个 private/protected成员, 并且它们都是来自同一处声明时,这两个类型才是兼容的

    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; // 错误: Animal 与 Employee 不兼容. 因为Employee的name来源与Animal不同
    

protected

  • private修饰符的行为很相似,但有一点不同, protected成员除了可以在声明它的类的内部访问,在派生类中仍然可以访问

    class Person {
      protected name: string;
      constructor(name: string) { this.name = name; }
    }
    
    class Employee extends Person {
      constructor(name: string) {
        super(name)
     }
      public getElevatorPitch() {
          return `Hello, my name is ${this.name}`; // 在派生类中正常访问
      }
    }
    
    let howard = new Employee("Howard");
    console.log(howard.getElevatorPitch());
    console.log(howard.name); // 错误 在外部无法访问
    
  • 构造函数也可以被标记成 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 是只读的.
    

参数属性

  • 参数属性可以在将成员的声明和赋值合并至构造函数内

    // 未使用参数属性
    class Octopus {
        readonly name: string;
        constructor (theName: string) {
            this.name = theName;
        }
    }
    // 使用参数属性,省略了theName,将声明和初始化合成一步
    class Octopus {
          // readonly 修饰符可以替换成private,public或protected
        constructor(readonly name: string) {
        }
    }
    

静态属性

  • 通过static 关键字定义,通过类名访问

    class Grid {
      static origin = { x: 0, y: 0 };
    }
    console.log(Grid.origin.x);
    

抽象类

  • 不能直接被实例化,作为其它派生类的基类使用,与接口类似,不同在于抽象类可以包含成员的实现细节;

  • 通过abstract关键字是定义抽象类和在抽象类内部定义抽象方法

    abstract class Animal {
        abstract makeSound(): void;
        move(): void {
            console.log('roaming the earch...');
        }
    }
    
  • 抽象类中的抽象方法不包含具体实现并且必须在派生类中实现,在派生类的构造函数中必须调用 super()

构造函数

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

let greeter: Greeter;
greeter = new Greeter("world");
console.log(greeter.greet());

编译成js后

let Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();

let greeter;
greeter = new Greeter("world");
console.log(greeter.greet());

你可能感兴趣的:(TypeScript学习摘要(三)——类)