TypeScript笔记③—面向对象(类)

面向对象

类class

我们先看一个使用类的例子:

class Student {
    // 学生姓名
    public readonly name: string;
    // 学生班级
    private clazz: number;
    // 学生年龄
    private age?: number;
    // 构造器
    constructor(name: string, clazz: number, age?: number) {
        this.name = name;
        this.age = age;
        this.clazz = clazz;
    }
    // 方法
    sayHello() {
        console.log("Hello! My name is " + this.name);
    }
}

let Alice = new Student("Alice", 1);
let Bob = new Student("Bob", 2, 18);

如果你使用过C#或Java,你会对这种语法非常熟悉。 我们声明一个Student类。

这个类有3个属性:name, clazz, age,一个构造器constructor,一个方法sayHello()

在引用任何一个类成员的时候都用了this。 它表示我们访问的是类的成员。

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

readonly修饰符

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

class Student {
    readonly name: string;
    constructor (name: string) {
        this.name = name;
    }
}
let Bob = new Student("Bob");
Bob.name = "Alice"; // 错误! name 是只读的.

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

默认为public

在上面的例子里,我们可以自由的访问程序里定义的成员。 如果你对其它语言中的类比较了解,就会注意到我们在之前的代码里并没有使用public来做修饰;例如,C#要求必须明确地使用public指定成员是可见的。 在TypeScript里,成员都默认为public

你也可以明确的将一个成员标记成public。 我们可以用下面的方式来重写上面的Animal类:

class Animal {
    public name: string;
    public constructor(name: string) { this.name = name; }
}
let dog = new Animal("dog");
console.log(dog.name); //输出dog
理解private

当成员被标记成private时,它就不能在声明它的类的外部访问。比如:

class Animal {
    private name: string;
    constructor(name: string) { this.name = name; }
}
let dog = new Animal("dog");
console.log(dog.name); //错误,name是私有的

private标记的成员在子类中也无法进行访问。比如:

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

class dog extends Animal {
    getName() {
        // super调用父类元素
        return super.name; //错误,private成员无法在子类调用
    }
}
理解protected

protected修饰符与private修饰符的行为很相似,但有一点不同,protected成员在子类中仍然可以访问。例如:

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

class dog extends Animal {
    getName(): string {
        return super.name; // 正确
    }
}

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

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

class dog extends Animal {
    constructor(name: string) {
        super(name); // 调用父类构造器
    }
    getName(): string {
        return super.name;
    }
}

let new_cat = new Animal("cat"); // 错误
let new_dog = new dog("dog"); // 正确

存取器

TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。

下面来看如何把一个简单的类改写成使用getset。 首先,我们从一个没有使用存取器的例子开始。

class Student {
    // 学生姓名
    private _name: string;
    constructor(_name: string) {
        this._name = _name;
    }
    sayHello() {
        console.log("Hello! My name is " + this._name);
    }
    set name(name: string) {
        if (name) {
            this._name = name;
        } else {
            throw new Error("name cannot be empty!!!");
        }
    }
    get name() {
        return this._name;
    }
}
let Alice = new Student("Alice");

Alice.name = ""; // 将会报错Error("name cannot be empty!!!");
Alice.name = "Bob"; // 正确,调用set方法

console.log(Alice.name); // 调用get方法

允许随意设置name虽然方便,但是我们仍想在设置name强制执行某些约束。

在这个版本里,我们添加一个setter来检查newName的长度,以确保它满足数据库字段的最大长度限制。若它不满足,那么我们就抛一个错误来告诉客户端出错了。

为保留原有的功能,我们同时添加一个getter用来读取name

首先,存取器要求你将编译器设置为输出ECMAScript 5(ES5)或更高。 不支持降级到ECMAScript 3(ES3)。 其次,只带有get不带有set的存取器自动被推断为readonly。 这在从代码生成.d.ts文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。

静态类型

抽象类

构造函数

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值