基础概念
认识类的使用
类的定义
类的继承
类的成员修饰符
在TypeScript中,类的属性和方法支持三种修饰符: public、private、protected
public修饰的是在任何地方可见、公有的属性或方法,默认编写的属性就是public的;private修饰的是仅在同一类中可见、私有的属性或方法;protected修饰的是仅在类自身及子类中可见、受保护的属性或方法; ```javascript class Person { private name: string = “”// 封装了两个方法, 通过方法来访问name getName() { return this.name }
setName(newName) { this.name = newName } }
const p = new Person() console.log(p.getName()) p.setName(“why”)
```javascript// protected: 在类内部和子类中可以访问class Person {protected name: string = "123"}class Student extends Person {getName() {return this.name}}const stu = new Student()console.log(stu.getName())
只读属性 readonly
如果有一个属性我们不希望外界可以任意的修改,只希望确定值后直接使用,那么可以使用readonly:
- 构造函数中可以给只读属性赋值进行初始化
- readonly 就相当于类中的 const ```javascript class Person { // 1.只读属性是可以在构造器中赋值, 赋值之后就不可以修改 // 2.属性本身不能进行修改, 但是如果它是对象类型, 对象中的属性是可以修改 readonly name: string age?: number readonly friend?: Person constructor(name: string, friend?: Person) { this.name = name this.friend = friend } }
const p = new Person(“why”, new Person(“kobe”)) console.log(p.name) console.log(p.friend)
// 不可以直接修改friend // p.friend = new Person(“james”) if (p.friend) { p.friend.age = 30 }
// p.name = “123”
<a name="GUKFr"></a>## getters/setters在前面一些私有属性我们是不能直接访问的,或者某些属性我们想要监听它的获取(getter)和设置(setter)的过程,<br />这个时候我们可以使用存取器。它不是函数,和 Java 中的不一样。新语言都有这种新的结构。```javascriptclass Person {private _name: stringconstructor(name: string) {this._name = name}// 访问器setter/getter// setterset name(newName) {this._name = newName}// getterget name() { // 相当于有个属性 namereturn this._name}}const p = new Person("why")p.name = "coderwhy"console.log(p.name)
静态成员
前面我们在类中定义的成员和方法都属于对象级别的, 在开发中, 我们有时候也需要定义类级别的成员和方法。
class Student {static time: string = "20:00"static attendClass() {console.log("去学习~")}}console.log(Student.time) // 直接通过类来访问Student.attendClass()
抽象类 abstract
我们知道,继承是多态使用的前提。在定义很多通用的调用接口时, 我们通常会让父类引用做形参。使用时,就会传入子类实例,通过多态让子类来实现具体的功能。
function makeArea(shape: Shape) {return shape.getArea()}class Shape {// 计算图形面积getArea() {}}class Rectangle extends Shape {private width: numberprivate height: numberconstructor(width: number, height: number) {super()this.width = widththis.height = height}getArea() {return this.width * this.height}}class Circle extends Shape {private r: numberconstructor(r: number) {super()this.r = r}getArea() {return this.r * this.r * 3.14}}const rectangle = new Rectangle(20, 30)const circle = new Circle(10)console.log(makeArea(rectangle))console.log(makeArea(circle))
所以,父类本身可能并不需要对某些方法进行具体的实现。那如果给 makeAreg 函数直接传入父类实例就会造成错误。因此父类中定义的方法,,我们可以定义为抽象方法。
什么是 抽象方法? 在 TypeScript 中没有具体实现的方法(没有方法体),就是抽象方法。
- 抽象方法,必须存在于 抽象类 中;
- 抽象类是使用 abstract 声明的类;
抽象类有如下的特点:
- 抽象类是不能被实例化(也就是不能通过new创建)
抽象方法必须被子类实现,除非子类是个抽象类;
abstract class Shape {abstract getArea(): number}
类的类型
类本身也是可以作为一种数据类型: ```javascript class Person { name: string = “123” eating() {
} }
// 类作为一个类型,字面类要和 Person 类结构一样 const p1: Person = { name: “why”, eating() {
} }
function printPerson(p: Person) { console.log(p.name) }
printPerson(new Person())
// 应用场景:直接将类本体当参数传入时,限制传参时乱写 printPerson({name: “kobe”, eating: function() {}}) ```
