setter 和 getter
有时候我们需要对内部属性做一些保护,不能在类的外部访问,使用private。
但有时候我们希望对内容做一些处理之后再将其暴露出来使用。
我们可以通过 getter/setter来满足。
class Person {constructor(private name: string) {}/*这里的意思是,我定义了一个getName属性,虽然看起来是个方法,但在类的外部以属性的形式调用,返回的是this.name这个私有属性这样的做法有什么意义呢?name 作为私有属性是不想被外部直接调用的,我们通过getter这样的写法,可以对数据处理后,再让外界调用,比如:加密这样可以确保数据的安全性,很多时候getter的作用在于这里*/get getName() {return this.name + 'rose';}}const person = new Person('cos');// person.name // 这样是会报红的。console.log(person.getName)
我们一般会在私有属性名称之前,加一个下划线,大部分语言其实都是这么操作的。
class Person {constructor(private _name: string) {}/*我们一般会在私有属性名称之前,加一个下划线*/get name() {return this._name;}}const person = new Person('cos');console.log(person.name)
因为 _name 是私有属性,所以是不能直接使用 this.name 进行赋值的
我们可以使用setter 来处理这个。
class Person {constructor(private _name: string) {}get name() {return this._name + ' wang';}set name(name: string) {// 这里也可以对_name 做一些处理const realName = name.split(' ')[0]this._name = realName;}}const person = new Person('cos');console.log(person.name) // cos wangperson.name = 'rose wang';console.log(person.name) // rose wang
单例模式
单例模式:通过单例模式的方法创建的类在当前进程中只有一个实例
那么我们首先就要限制住,不能在外部通过 new Demo()的像是来创建实例
如果我写了 private 那么就会变为私有的 constructor,
外部就不能通过 new 的形式创建 实例。
这样就规避了通过new来创建实例的写法。
那如何去创建唯一的demo实例?
class Demo {private constructor() {}// 写public getInstance() 是不能在类上面获取到这个属性的// 如果想要在类上面去使用一个属性的话,可以使用static// static 表示把这个方法挂在类上面,而不是类的实例上static getInstance() {// 此时我希望通过 Demo.getInstance() 返回一个Demo的实例。可以如下写:return new Demo()}}const demo1 = Demo.getInstance();const demo2 = Demo.getInstance();//但是这样写的时候,每次执行都是new 了一个新的实例,则,demo1 和 demo2指向了不同的实例。
但是这样写的时候,每次执行都是new 了一个新的实例,则,demo1 和 demo2指向了不同的实例。我们改造如下:
class Demo {// 定义的instance的目的就是为了存储new出来的demoprivate static instance: Demo;private constructor(public name: string) {}static getInstance() {if(!this.instance) {this.instance = new Demo('mock');}return this.instance;// 这样写demo1 和 demo2 是相等的。}}const demo1 = Demo.getInstance();const demo2 = Demo.getInstance();console.log(demo1.name)console.log(demo2.name)
readonly
class Person {public readonly name: string;constructor(name: string) {this.name = name;}}const p1 = new Person('cos');// p1.name = 'rose'; // name为只读属性的话,这里就不能对其重新赋值了console.log(p1.name);
抽象类
如果多个类有一些通性,
那么我们就可以定义一些抽象类
注意:抽象类只能被继承,而不能直接被实例化
// 这3个图象的类,都应该有求面积的方法// 我们可以给每个类定义一个 getArea() 方法,虽然每个类,// 计算面积的方法是不一样的,但是都有类似的方法。abstract class Geom {// 抽象类中也可以定义一些具体的属性或者方法width: number;radius: number;// 如果给类的一个方法加了 abstract 的话,就意味着这个方法的具体实现也是抽象的// 我们也无法确定具体是怎么实现,所以只能定义一下这个方法而无法具体实现getType() {return 'Geom';}abstract getArea(): number;}// 表示 Circle 是抽象类Geom 的实现类class Circle extends Geom {// 直接这么写会报错,// 子类如果继承了抽象类,抽象类中如果有抽象方法,必须自己去实现这个抽象方法getArea() {return 123;}}class Sqare {}class Triangle {}
抽象类对比接口
抽象类和接口有点类似,
抽象类是把类相关的东西抽象出来
而接口是把对象等通用的东西抽象出来
interface Teacher {name: string,teachAge: number}interface Student {name: string,age: number}interface Driver {name: string,age: number}const teacher = {name: 'cos',teachAge: 20}const student = {name: 'rose',age: 18}const driver = {name: 'jack',age: 18}const getUserInfo = (user: (Teacher | Student)) => {console.log(user.name);}getUserInfo(teacher)getUserInfo(student)getUserInfo(driver)
上述的代码中每一项 interface , 都有name属性,所以我们可以继续在做一层抽象,
interface People {name: string;}interface Teacher extends People {teachAge: number}interface Student extends People {age: number}interface Driver extends People {age: number}const teacher = {name: 'cos',teachAge: 20}const student = {name: 'rose',age: 18}const driver = {name: 'jack',age: 18}const getUserInfo = (user: People) => {console.log(user.name);}getUserInfo(teacher)getUserInfo(student)getUserInfo(driver)
