zoukankan      html  css  js  c++  java
  • TypeScript语言学习笔记(2)接口,类

    接口

    // 在参数类型中定义约束
    function printLabel(labelledObj: { label: string }) {
        console.log(labelledObj.label);
    }
    let myObj = {size: 10, label: "Size 10 Object"};
    printLabel(myObj);
    // 定义并使用接口
    // 不需要显式继承接口(鸭子类型)
    interface LabelledValue {
        label: string;
    }
    function printLabel(labelledObj: LabelledValue) {
        console.log(labelledObj.label);
    }
    let myObj = {size: 10, label: "Size 10 Object"};
    printLabel(myObj);
    // 可选接口(属性加问号)
    interface SquareConfig {
        color?: string;
        width?: number;
    }
    function createSquare(config: SquareConfig): {color: string; area: number} {
        let newSquare = {color: "white", area: 100};
        if (config.color) {
            newSquare.color = config.color;
        }
        if (config.width) {
            newSquare.area = config.width * config.width;
        }
        return newSquare;
    }
    let mySquare = createSquare({color: "black"});
    // 强类型,防止使用接口之外的属性
    interface SquareConfig {
        color?: string;
        width?: number;
    }
    function createSquare(config: SquareConfig): { color: string; area: number } {
        let newSquare = {color: "white", area: 100};
        if (config.clor) {
            // Error: Property 'clor' does not exist on type 'SquareConfig'
            newSquare.color = config.clor;
        }
        if (config.width) {
            newSquare.area = config.width * config.width;
        }
        return newSquare;
    }
    let mySquare = createSquare({color: "black"});
    // 只读属性
    interface Point {
        readonly x: number;
        readonly y: number;
    }
    let p1: Point = { x: 10, y: 20 };
    p1.x = 5; // error!
    // 只读数组
    let a: number[] = [1, 2, 3, 4];
    let ro: ReadonlyArray<number> = a;
    ro[0] = 12; // error!
    ro.push(5); // error!
    ro.length = 100; // error!
    a = ro; // error!
    a = ro as number[];
    // 额外属性检查
    interface SquareConfig {
        color?: string;
        width?: number;
    }
    function createSquare(config: SquareConfig): { color: string; area: number } {
        // ...
    }
    // error: Object literal may only specify known properties, but 'colour' does not exist in type 'SquareConfig'. Did you mean to write 'color'?
    let mySquare = createSquare({ colour: "red",  100 });
    // 通过类型断言来绕过额外属性检查
    let mySquare = createSquare({  100, opacity: 0.5 } as SquareConfig);
    // 给接口添加任意多的额外的属性
    interface SquareConfig {
        color?: string;
        width?: number;
        [propName: string]: any;
    }
    // 不用字面量也可以绕过额外属性检查
    let squareOptions = { colour: "red",  100 };
    let mySquare = createSquare(squareOptions);
    // 变量和接口之间必须有共同的属性,不然通不过检查
    let squareOptions = { colour: "red" };
    let mySquare = createSquare(squareOptions);
    // 函数类型
    // 使用接口来描述函数类型
    interface SearchFunc {
        (source: string, subString: string): boolean;
    }
    // 使用函数类型接口
    let mySearch: SearchFunc;
    mySearch = function(source: string, subString: string) {
        let result = source.search(subString);
        return result > -1;
    }
    // 函数的参数名不需要匹配
    let mySearch: SearchFunc;
    mySearch = function(src: string, sub: string): boolean {
        let result = src.search(sub);
        return result > -1;
    }
    // 函数的参数类型可以省略
    let mySearch: SearchFunc;
    mySearch = function(src, sub) {
        let result = src.search(sub);
        return result > -1;
    }
    // 函数的返回类型必须匹配
    let mySearch: SearchFunc;
    // error: Type '(src: string, sub: string) => string' is not assignable to type 'SearchFunc'.
    // Type 'string' is not assignable to type 'boolean'.
    mySearch = function(src, sub) {
      let result = src.search(sub);
      return "string";
    };
    // 下标类型
    // 使用接口来描述下标类型
    interface StringArray {
        [index: number]: string;
    }
    let myArray: StringArray;
    myArray = ["Bob", "Fred"];
    let myStr: string = myArray[0];
    // 只支持两种下标类型:number 和 string
    // 可以同时支持两种下标类型,但是返回类型必须兼容
    class Animal {
        name: string;
    }
    class Dog extends Animal {
        breed: string;
    }
    // Error: indexing with a numeric string might get you a completely separate type of Animal!
    interface NotOkay {
        [x: number]: Animal;
        [x: string]: Dog;
    }
    // 如果支持下标类型,那么所有属性的类型必须兼容于下标类型的返回类型
    interface NumberDictionary {
        [index: string]: number;
        length: number;    // ok, length is a number
        name: string;      // error, the type of 'name' is not a subtype of the indexer
    }
    interface NumberOrStringDictionary {
        [index: string]: number | string;
        length: number;    // ok, length is a number
        name: string;      // ok, name is a string
    }
    // 只读下标类型
    interface ReadonlyStringArray {
        readonly [index: number]: string;
    }
    let myArray: ReadonlyStringArray = ["Alice", "Bob"];
    myArray[2] = "Mallory"; // error!
    // 类类型
    // 在类中实现接口(属性)
    interface ClockInterface {
        currentTime: Date;
    }
    class Clock implements ClockInterface {
        currentTime: Date = new Date();
        constructor(h: number, m: number) { }
    }
    // 在类中实现接口(方法)
    interface ClockInterface {
        currentTime: Date;
        setTime(d: Date): void;
    }
    class Clock implements ClockInterface {
        currentTime: Date = new Date();
        setTime(d: Date) {
            this.currentTime = d;
        }
        constructor(h: number, m: number) { }
    }
    // 类的静态部分和实例部分
    // 类的静态部分不能用于实现接口
    // 出错示例
    interface ClockConstructor {
        new (hour: number, minute: number);
    }
    class Clock implements ClockConstructor {
        currentTime: Date;
        constructor(h: number, m: number) { }
    }
    // 正确示例1
    interface ClockConstructor {
        new (hour: number, minute: number): ClockInterface;
    }
    interface ClockInterface {
        tick(): void;
    }
    function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
        return new ctor(hour, minute);
    }
    class DigitalClock implements ClockInterface {
        constructor(h: number, m: number) { }
        tick() {
            console.log("beep beep");
        }
    }
    class AnalogClock implements ClockInterface {
        constructor(h: number, m: number) { }
        tick() {
            console.log("tick tock");
        }
    }
    let digital = createClock(DigitalClock, 12, 17);
    let analog = createClock(AnalogClock, 7, 32);
    // 正确示例2(使用类表达式)
    interface ClockConstructor {
      new (hour: number, minute: number);
    }
    interface ClockInterface {
      tick();
    }
    const Clock: ClockConstructor = class Clock implements ClockInterface {
      constructor(h: number, m: number) {}
      tick() {
          console.log("beep beep");
      }
    }
    // 扩展接口
    interface Shape {
        color: string;
    }
    interface Square extends Shape {
        sideLength: number;
    }
    let square = {} as Square;
    square.color = "blue";
    square.sideLength = 10;
    // 扩展多个接口
    interface Shape {
        color: string;
    }
    interface PenStroke {
        penWidth: number;
    }
    interface Square extends Shape, PenStroke {
        sideLength: number;
    }
    let square = {} as Square;
    square.color = "blue";
    square.sideLength = 10;
    square.penWidth = 5.0;
    // 混合类型
    interface Counter {
        (start: number): string;
        interval: number;
        reset(): void;
    }
    function getCounter(): Counter {
        let counter = (function (start: number) { }) as Counter;
        counter.interval = 123;
        counter.reset = function () { };
        return counter;
    }
    let c = getCounter();
    c(10);
    c.reset();
    c.interval = 5.0;
    // 扩展类的接口
    // 接口扩展类,意味着继承类的所有成员(包括private,protected成员)的签名(没有实现)
    // 扩展某个含有private,protected成员的类的接口,只能由该类的子类来实现
    class Control {
        private state: any;
    }
    interface SelectableControl extends Control {
        select(): void;
    }
    class Button extends Control implements SelectableControl {
        select() { }
    }
    class TextBox extends Control {
        select() { }
    }
    // Error: Property 'state' is missing in type 'Image'.
    class Image implements SelectableControl {
        private state: any;
        select() { }
    }
    class Location {
    
    }
    

    // 类
    class Greeter {
        greeting: string;
        constructor(message: string) {
            this.greeting = message;
        }
        greet() {
            return "Hello, " + this.greeting;
        }
    }
    let greeter = new Greeter("world");
    // 继承
    class Animal {
        move(distanceInMeters: number = 0) {
            console.log(`Animal moved ${distanceInMeters}m.`);
        }
    }
    class Dog extends Animal {
        bark() {
            console.log('Woof! Woof!');
        }
    }
    const dog = new Dog();
    dog.bark();
    dog.move(10);
    dog.bark();
    // 继承2
    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);
    // Slithering...
    // Sammy the Python moved 5m.
    // Galloping...
    // Tommy the Palomino moved 34m.
    
    // public private protected 修饰符
    // 缺省为 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; // Error: 'name' is private;
    // 兼容性
    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: 'Animal' and 'Employee' are not compatible
    // 理解 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
    // protected 构造器
    class Person {
        protected name: string;
        protected constructor(theName: string) { this.name = theName; }
    }
    // Employee can extend 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"); // Error: The 'Person' constructor is protected
    // 只读修饰符
    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"; // error! name is readonly.
    // 参数属性
    // 通过参数创建并初始化属性
    class Octopus {
        readonly numberOfLegs: number = 8;
        constructor(readonly name: string) {
        }
    }
    // 访问器
    // 没有getter和setter的例子
    class Employee {
        fullName: string;
    }
    let employee = new Employee();
    employee.fullName = "Bob Smith";
    if (employee.fullName) {
        console.log(employee.fullName);
    }
    // 含有getter和setter的例子
    const fullNameMaxLength = 10;
    class Employee {
        private _fullName: string;
        get fullName(): string {
            return this._fullName;
        }
        set fullName(newName: string) {
            if (newName && newName.length > fullNameMaxLength) {
                throw new Error("fullName has a max length of " + fullNameMaxLength);
            }
            this._fullName = newName;
        }
    }
    let employee = new Employee();
    employee.fullName = "Bob Smith";
    if (employee.fullName) {
        console.log(employee.fullName);
    }
    // 静态属性
    class Grid {
        static origin = {x: 0, y: 0};
        calculateDistanceFromOrigin(point: {x: number; y: number;}) {
            let xDist = (point.x - Grid.origin.x);
            let yDist = (point.y - Grid.origin.y);
            return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
        }
        constructor (public scale: number) { }
    }
    let grid1 = new Grid(1.0);  // 1x scale
    let grid2 = new Grid(5.0);  // 5x scale
    console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
    console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
    // 抽象类
    abstract class Animal {
        abstract makeSound(): void;
        move(): void {
            console.log("roaming the earth...");
        }
    }
    // 抽象类 2
    abstract class Department {
        constructor(public name: string) {
        }
        printName(): void {
            console.log("Department name: " + this.name);
        }
        abstract printMeeting(): void; // must be implemented in derived classes
    }
    class AccountingDepartment extends Department {
        constructor() {
            super("Accounting and Auditing"); // constructors in derived classes must call super()
        }
        printMeeting(): void {
            console.log("The Accounting Department meets each Monday at 10am.");
        }
        generateReports(): void {
            console.log("Generating accounting reports...");
        }
    }
    let department: Department; // ok to create a reference to an abstract type
    department = new Department(); // error: cannot create an instance of an abstract class
    department = new AccountingDepartment(); // ok to create and assign a non-abstract subclass
    department.printName();
    department.printMeeting();
    department.generateReports(); // error: method doesn't exist on declared abstract type
    // 高级技巧
    // 构造器函数
    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());
    // 相当于
    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());
    // 使用构造器函数
    class Greeter {
        static standardGreeting = "Hello, there";
        greeting: string;
        greet() {
            if (this.greeting) {
                return "Hello, " + this.greeting;
            }
            else {
                return Greeter.standardGreeting;
            }
        }
    }
    let greeter1: Greeter;
    greeter1 = new Greeter();
    console.log(greeter1.greet());
    let greeterMaker: typeof Greeter = Greeter;
    greeterMaker.standardGreeting = "Hey there!";
    let greeter2: Greeter = new greeterMaker();
    console.log(greeter2.greet());
    // 将类用作接口
    class Point {
        x: number;
        y: number;
    }
    interface Point3d extends Point {
        z: number;
    }
    let point3d: Point3d = {x: 1, y: 2, z: 3};
    
  • 相关阅读:
    Python入门系列——第17篇
    Python入门系列——第16篇
    Python入门系列——第15篇
    Python入门系列——第14篇
    Python入门系列——第13篇
    Python入门系列——第12篇
    python入门系列——第11篇
    Python入门系列——第10篇
    Python入门系列——第9篇
    Python入门系列——第8篇
  • 原文地址:https://www.cnblogs.com/zwvista/p/9016923.html
Copyright © 2011-2022 走看看