1.类
- 我们声明一个
Greeter类。这个类有3个成员:一个叫做greeting的属性,一个构造函数和一个greet方法。- 我们在引用任何一个类成员的时候都用了
this。 它表示我们访问的是类的成员。- 我们使用
new构造了Greeter类的一个实例。 它会调用之前定义的构造函数,创建一个Greeter类型的新对象,并执行构造函数初始化它。
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
let greeter = new Greeter("world");
2.继承
- 继承就是类从基类中继承了属性和方法。
Dog是一个 派生类,它派生自Animal基类,通过extends关键字。 派生类通常被称作 子类,基类通常被称作 超类。因为
Dog继承了Animal的功能,因此我们可以创建一个Dog的实例,它能够bark()和move()
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();
class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = 0) {
console.log(this);
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);
在控制台上面执行
//test.ts上面的文件
tsc test.ts
tsc test.js
打印

可以看到

此外还有几点需要注意
- 在派生类的构造函数(constructor)里面访问this的属性之前必须调用super()(作用是执行基类的构造函数)
- 可以在子类里面重写父类的方法。move()
- 即使
tom被声明为Animal类型,但因为它的值是Horse,调用tom.move(34)时,它会调用Horse里重写的方法
3.公共,私有与受保护的修饰符
默认为 public
在TypeScript里,成员都默认为 public。
理解 private
当成员被标记成 private时,它就不能在声明它的类的外部访问。比如:Aniaml.name也不行。只能类的内部访问
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
new Animal("Cat").name; // 错误: 'name' 是私有的.
理解 protected
protected修饰符与private修饰符的行为很相似,但有一点不同,protected成员在派生类中仍然可以访问。例如getElevatorPitch方法中的${this.name}- 我们不能在
Person类外使用name,但是我们仍然可以通过Employee类的实例方法访问,因为Employee是由Person派生而来的。
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 per = new Person('tes');
// per.name; //错误 属性“name”受保护,只能在类“Person”及其子类中访问。
// Person.name;//错误 编译无法通过Property 'name' does not exist on type 'typeof Person'.
let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
// console.log(howard.name); // 错误 属性“name”受保护,只能在类“Person”及其子类中访问。
![]()
- 构造函数也可以被标记成
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' 的构造函数是被保护的.
4.readonly修饰符
你可以使用 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 是只读的.
参数属性
适用情况(我们必须在Octopus类里定义一个只读成员 name和一个参数为 theName的构造函数,并且立刻将 theName的值赋给 name,这种情况经常会遇到。)
看下面将声明和赋值合并到一处,和上面的代码效果是一样的(当然此处的readonly换成priavte,public等都是可以的)
class Octopus {
readonly numberOfLegs: number = 8;
constructor(readonly name: string) {
}
}
5.存取器
TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
首先看下面例子
class Employee {
fullName: string;
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
console.log(employee.fullName);
}
我们现在对上面的例子进行改写
let passcode = "secret passcode";
class Employee {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (passcode && passcode == "secret passcode") {
this._fullName = newName;
}
else {
console.log("Error: Unauthorized update of employee!");
}
}
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
alert(employee.fullName);
}
- 我们先检查用户密码是否正确,然后再允许其修改员工信息
- 我们可以修改一下密码,来验证一下存取器是否是工作的。当密码不对时,会提示我们没有权限去修改员工。
以下需要注意
- 首先,存取器要求你将编译器设置为输出ECMAScript 5或更高。 不支持降级到ECMAScript 3。所以在编译的时候可以这样写node test.ts --target es6
- 只带有
get不带有set的存取器自动被推断为readonly。 这在从代码生成.d.ts文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。
本文深入解析TypeScript中的类、继承、修饰符、readonly属性及存取器,通过实例展示如何有效控制类成员访问,适合希望提升TypeScript技能的开发者。
1482

被折叠的 条评论
为什么被折叠?



