- A+
所属分类:Web前端
创建一个对象
class Person{ public name:string; public age:number; constructor(name:string, age:number){ this.name = name; this.age = age; } } let a = new Person("测试", 15); console.log(a.name + " --- " + a.age)
继承
class NewPerson extends Person{ public sex: number; constructor(sex: number){ this.sex = sex; } }
由图可见,上面的继承是不正常的,所以这里需要调用其super方法
class NewPerson extends Person{ public sex: number; constructor(name:string,age:number,sex: number){ super(name,age); this.sex = sex; } }
私有属性
class PrivatePerson{ private name:string; constructor(name:string){ this.name = name; } } let c = new PrivatePerson("wz"); console.log(c.name) // 提示报错
这个就是私有属性,那么我们该怎么访问这个私有属性呢?
class PrivatePerson{ private name:string; constructor(name:string){ this.name = name; } get getName(){ return this.name; } } let c = new PrivatePerson("wz"); console.log(c.getName)
通过上述的
get
修饰的属性(看起来更像一个方法),便可以获取到私有属性,最后可以通过c.getName
获取到
有get
获取属性,那么是否有set
设置属性呢???
class PrivatePerson{ private name:string; constructor(name:string){ this.name = name; } get getName(){ return this.name; } set setName(name: string){ this.name = name } } let c = new PrivatePerson("wz"); console.log(c.getName) c.setName = "哈哈"; console.log(c.getName)
通过上面
set
的案例,我们应该清楚的看到,其实get
和set
修饰的都不是方法,而是属性,因为方法的调用fn()
,而这个看起来更像是属性的写法,所以这里注意c.setName = "哈哈"
,既然这样,为了美观,我们将上面的进行一个修改
class PrivatePerson{ private _name:string; constructor(name:string){ this._name = name; } get name(){ return this._name; } set name(name: string){ this._name = name } } let c = new PrivatePerson("wz"); console.log(c.name) c.name = "哈哈"; console.log(c.name)
这样看起来就完全一样了
私有属性作用是什么呢?
实现单例模式
class SimpleObject { //静态方法中只能调用静态变量 private static simpleInfo: SimpleObject; //私有化构造函数,让其无法被外界`new`出来 private constructor(){} //提供公共的静态的获取实例方法 public static getInstance(){ //判断实例是否存在 if(!this.simpleInfo){ //不存在就实例化一个 this.simpleInfo = new SimpleObject(); } //返回实例 return this.simpleInfo; } }
以上的单例模式很简单,但是也需要注意几个小点
- 因为我们需要实现"单例模式",所以必须要限制实例化的方式,只能由我们内部提供,所以将
构造函数私有化
,在前面加上private
- 获取实例方法: 因为我们把构造函数
constructor
私有化了,所以外部无法使用new
关键字实例化对象,我们必须要提供的获取实例方法getInstance
必须可以在不实例化的情况下调用,所以这个方法必须使用static
修饰 - 静态方法只能访问静态的数据,所以这里的实例
simpleInfo
也是静态的,并且为了不让其被外部直接调用,所以加上private
实现部分属性只能获取,而无法修改
- 私有属性实现
class PriPerson{ private _name:string; constructor(name :string){ this._name = name; } get name(){ return this._name } } let e = new PriPerson("一个人"); console.log(e.name) e.name = "不可修改" //报错
- readonly实现
class PriPerson{ public readonly name:string; constructor(name :string){ this.name = name; } } let e = new PriPerson("一个人"); console.log(e.name) e.name = "不可修改" //报错
抽象类
有时候需要分类,同一类事物有着公共的特性,公共的方法(但是每个之间实现不同),这个时候我们就可以定义个抽象类,抽出相同的,相同的方法
abstract class Animal{ getEatOrgan(){ return "嘴"; } abstract eat():string; } class People extends Animal{ eat(){ return "使用手抓吃饭"; } } class Pig extends Animal{ eat(){ return "使用嘴拱着吃"; } } let animals : [string, string] = ["man", "pig"]; animals.forEach((animal) => { let unknownAnimal:Animal; unknownAnimal = animal === "man" ? new People() : new Pig(); console.log("吃饭通用器官:" + unknownAnimal.getEatOrgan(), "各自吃饭方式: " + unknownAnimal.eat()); })
结果
接口的继承
我们常常会定义一些接口,用于类型定义及检测,像下面一样
interface Student{ name:string, age:number } interface Teacher{ name:string, sex:string } const sayHello = (user) => { console.log(user.name) } let st: Student ={ name: '张珊', age:18 } let te :Teacher = { name:"历史", sex:"男" } sayHello(st); sayHello(te);
但是我们发现,
sayHello
中参数user
的推断类型是
这个不是我们想要的,所以我们去定义这个user
的类型,用什么呢?是Student
还是Teacher
,当然是我全都要了
const sayHello = (user: Student | Teacher) => { console.log(user.name) }
思考,当我们新建对象的时候,这个参数类型是不是一直在添加呢?
这个时候就需要使用我们的接口继承(提取出相同的属性,方法,然后其他子类继承该接口)
interface Person{ name:string } interface Student extends Person{ age:number } interface Teacher extends Person{ sex:string } const sayHello = (user:Person) => { console.log(user.name) } let st: Student ={ name: '张珊', age:18 } let te :Teacher = { name:"历史", sex:"男" } sayHello(st); sayHello(te);