
ts从入门到进阶—4.1类
发布日期:2021-05-06 19:34:52
浏览次数:26
分类:精选文章
本文共 5030 字,大约阅读时间需要 16 分钟。
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.tstsc 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 能够继承 Personclass 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
文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年03月27日 16时28分22秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
《算法导论》第二章笔记
2019-03-06
HTML `capture` 属性
2019-03-06
CSS盒子模型
2019-03-06
HTML节点操作
2019-03-06
浏览器页面呈现过程
2019-03-06
HTML5新特性
2019-03-06
async/await剖析
2019-03-06
cmp命令
2019-03-06
一次编辑
2019-03-06
od命令
2019-03-06
简单工厂模式
2019-03-06
代理模式
2019-03-06
Js中Currying的应用
2019-03-06
长按键入
2019-03-06
Vuex和普通全局对象
2019-03-06
上升下降字符串
2019-03-06
JavaScript中的链式调用
2019-03-06
day-04-列表
2019-03-06
day-13-匿名函数-内置函数2-闭包
2019-03-06
Linux 磁盘管理(df fu fdisk mkfs mount)
2019-03-06