ts / 接口的定义使用 && 类结构属性方法(含private&set)(二)

接口

定义方式

直联定义
function printLabel(labelledObj: { label: string }) {
  console.log(labelledObj.label);
}
引用定义
interface LabelledValue {
  label: string;
}

function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label);
}

ts会检查参数是否含有接口中指定的项,其他多余项和项的顺序不参与判断

基础语法

可选属性

可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。

interface SquareConfig {
  color?: string;
  width?: number;
}
只读属性

只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly来指定只读属性

interface Point {
    readonly x: number;
    readonly y: number;
}

相似:let ro: ReadonlyArray = a;

该数组无法被更改了

额外的属性检查

error: ‘colour’ not expected in type ‘SquareConfig’

断言
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);

上文适合,当函数createSquare的参数类型为SquareConfig接口的指定,但是包含SquareConfig接口未指出的属性时

给出兼容项
interface SquareConfig {
    color?: string;
    width?: number;
    [propName: string]: any;
}

在这我们要表示的是SquareConfig可以有任意数量的属性,并且只要它们不是colorwidth,那么就无所谓它们的类型是什么

接口类型

函数类型

函数类型实质上是指定函数的参数和返回值类型

interface SearchFunc {
  (source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string): boolean {
  let result = source.search(subString);
  return result > -1;
}
索引类型
定义索引接口
interface StringArray {
  [index: number]: string;
}

let myArray: StringArray;
myArray = ["Bob", "Fred"];

let myStr: string = myArray[0];
只读索引
interface ReadonlyStringArray {
    readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory"; // error!
类类型

接口制定类的部分属性与方法参数

interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}

class Clock implements ClockInterface {
    currentTime: Date;
    setTime(d: Date) {
        this.currentTime = d;
    }
    constructor(h: number, m: number) { }
}

接口继承

interface Shape {
    color: string;
}

interface PenStroke {
    penWidth: number;
}

interface Square extends Shape, PenStroke {
    sideLength: number;
}

let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;

结构初识

class Greeter {
    greeting: string; //声明属性 this调用类属性
    constructor(message: string) { // 构造函数
        this.greeting = message;
    }
    greet() { // 声明方法
        return "Hello, " + this.greeting;
    }
}
// 创建一个 Greeter类型的新对象,并执行构造函数初始化它。
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();

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

super调用基类/超类

在子类的构造函数中,调用超类的构造函数。

constructor(name: string) { super(name); }

调用超类的方法 可用在子类的方法重写中

super.move(distanceInMeters);

在构造函数里访问 this的属性之前,我们 一定要调用 super()

属性修饰词

public

在TypeScript里,成员都默认为 public

public name: string;
private

不能在声明它的类的外部访问。

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

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

派生类后,可以在派生类内部访问,实例化后可以通过方法访问,但是不能通过实例化后的对象直接访问

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

readonly

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

参数属性
constructor(readonly name: string) {
}

仅在构造函数里使用 readonly name: string参数来创建和初始化 name成员。 我们把声明和赋值合并至一处。

参数属性通过给构造函数参数前面添加一个访问限定符来声明。 使用 private限定一个参数属性会声明并初始化一个私有成员;对于 publicprotected来说也是一样。

存取器

set
set fullName(newName: string) {
    if (passcode && passcode == "secret passcode") {
        this._fullName = newName;
    }
    else {
        console.log("Error: Unauthorized update of employee!");
    }
}
get
get fullName(): string {
    return this._fullName;
}

静态属性

这些属性存在于类本身上面而不是类的实例上。

每个实例想要访问这个属性的时候,都要在 origin前面加上类名。 如同在实例属性上使用 this.前缀来访问属性一样,这里我们使用 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;
}

抽象类

abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。

不能创建一个抽象类的实例,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。

abstract class Department {

    constructor(public name: string) {
    }

    printName(): void {
        console.log('Department name: ' + this.name);
    }

    abstract printMeeting(): void; // 必须在派生类中实现
}

class AccountingDepartment extends Department {

    constructor() {
        super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
    }

    printMeeting(): void {
        console.log('The Accounting Department meets each Monday at 10am.');
    }

    generateReports(): void {
        console.log('Generating accounting reports...');
    }
}

let department: Department; // 允许创建一个对抽象类型的引用
department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
department.generateReports(); // 错误: 方法在声明的抽象类中不存在
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值