TypeScript是一种面向对象编程语言,面向对象编程的三大特征是封装、继承、多太。作为面向对象编程而言,类是实现面向对象编程最重要的手段。写这篇文章的主要目的在于总结总结一些在学习类时重要的知识点。
一、public、protected、private标示符
类在进行封装时,我们可以通过public、protected、private三个标示符控制类成员的访问权限。
public:可以自由的访问类的成员,类默认访问权限为public。
protected:可以在基类和子类中访问成员。
private:只可以在基类中访问成员。
我们通过一段代码来详细解释一下:
class Base {
public str1: string = "public";
protected str2: string = "protected";
private str3: string = "private";
public constructor() {
console.log("Base " + this.str1);
console.log("Base " + this.str2);
console.log("Base " + this.str3);
}
}
class Child extends Base {
public constructor() {
super();
console.log("Child " + this.str1);
console.log("Child " + this.str2);
console.log("Child " + this.str3); //错误:str3只能在Base类中访问
}
}
let child: Child = new Child();
console.log("Main " + child.str1);
console.log("Main " + child.str2); //错误:str2只能在Base类和Base类的子类中访问
console.log("Main " + child.str3); //错误:str3只能在Base类中访问
示例中,我们在Base类中定义了三个成员变量str1、str2、str3,分别把他们标示为public、protected、private。让Child类继承Base,并且在Base构造函数、Child构造函数、全局调用输出三个成员变量。我们可以看到,在Base类中访问三个成员没有任何问题。但在Child类中访问str3会报错,因为str3被标示为private。在全局中访问str2、str3也同样会报错,因为他们分别被标示为protected、private。
二、construction、extends、super
construction:类的构造函数
extends:类继承的关键字
super:子类调用基类的构造函数
示例:
class Base {
public constructor() {
console.log("Base");
}
}
class Child extends Base {
public constructor() {
super();
console.log("Child");
}
}
在Base类、Child类中construction()分别是两个类的构造函数。Child通过extends字段继承了Base类,在TypeScript中不支持多重继承,一个子类只能继承一个基类。在Child类的构造函数中使用super()来调用Base类的构造函数,这里需要特别一提的是在子类构造函数里访问this属性前必须要先调用super(),这是TypeScript强制执行的一条重要规则。
三、readonly
readonly:将属性设置为只读,readonly属性只能在声明和构造函数中初始化。
class Base {
public readonly str1: string = "hello world";
public constructor() {
this.str1 = "good morning";
}
public Say() {
this.str1 = "nice to meet you"; //错误:str1为只读属性,只能在声明和构造函数中初始化
}
}
四、get,set存取器
get、set:存取器定义的关键字。
在一个类中经常会有许多成员变量,我们经常会获取和修改这些成员变量的值。如示例:
class Base{
public member:string = "hello world";
}
let base:Base = new Base();
base.member = "good morning";
console.log(base.member);
示例中member成员被标记为public来使用,这样虽然很方便,但也会带来很多的麻烦。通常我们都会通过接口的方式来获取和修改成员变量,我们接着来改写,如下面示例:
class Base {
private member: string = "hello world";
public GetMember(): string {
return this.member;
}
public SetMember(s: string) {
this.member = s;
}
}
let base: Base = new Base();
base.SetMember("good morning");
console.log(base.GetMember());
我们在Base类中增加了GetMember()、SetMember()两个接口来获取和修改成员变量。这是用函数的方式来实现的。我们接下来再来看用存取器方式的实现。
class Base {
private member: string = "hello world";
public get Member(): string {
return this.member;
}
public set Member(s: string) {
this.member = s;
}
}
let base: Base = new Base();
base.Member = "good morning";
console.log(base.Member);
我们可以看到,存取器的定义与函数相似,只是在函数名前面标记了关键字get、set,并且存取器可以使用同样的命名。在使用时存取器可以像成员变量的语法方式使用,在代码风格上更加直观。
五、static
static:类的静态属性。
class Base {
public static member: string = "hello world";
public static Say() {
console.log(Base.member);
}
}
Base.Say();
console.log(Base.member);
static属性归属于类而不归属于实例,static属性的使用不需要实例化对象。
六、abstract
abstract是用来定义抽象类用的,抽象类的抽象方法不在基类中具体实现,而是在子类中具体实现方法。示例:
abstract class Base {
abstract Say(): void;
}
class Child1 extends Base {
public Say(): void {
console.log("hello world");
}
}
class Child2 extends Base {
public Say(): void {
console.log("good morning");
}
}
let child1 = new Child1();
child1.Say();
let child2 = new Child2();
child2.Say();
使用abstract字段将Base类定义为抽象类,并且在Base内部定义了一个抽象方法Say()。Child1和Child2通过继承Base类分别实现各自的Say()方法。
关于类详细的介绍大家可以查看官网文档。https://www.tslang.cn/docs/handbook/classes.html
下面是我的个人作品分享,有喜欢的朋友可以过来看看,希望大家喜欢。