本文共 4223 字,大约阅读时间需要 14 分钟。
概念:
代码展示:
// 接口interface IStorage { save(key: string, value: any): void; read(key: string): any;}// userinfo类class UserInfo { constructor(public name: string, public storage: IStorage) { } save() { this.storage.save('userinfo', JSON.stringify(this)); } read() { return this.storage.read('userinfo'); }}// LocalStorage类实现IStroage接口class LocalStorage implements IStorage { save(key: string, value: any): void { localStorage.setItem(key, value); } read(key: string) { return localStorage.getItem(key); }}let local = new LocalStorage();let userinfo = new UserInfo('zhufeng', local);console.log(userinfo.name);
代码解释:
现在代码里实现的是把传到UserInfo
的信息存入到本地存储里。
IStorage
接口,这个接口又两个方法,save() 存,read() 取。LocalStorage
类,让它去实现了IStroage
接口。new 一个 LocalStorage 的实例
,然后连带着信息传给Userinfo即可。重点来了:
看了我上面写的概念、代码、解释,你可能还是晕乎乎的。你的问题可能还是:什么是抽象。
别急,我们对着概念一步一步来看:
抽象主要是隐藏方法的实现,让调用者只关心有哪些功能而不是关心功能的实现。
UserInfo
类,UserInfo类 调用 storage 存储功能时,它需要知道 LocalStorage 怎么实现的吗?它不需要知道,他只需要知道通过 storage打点可以拿到save或read进行存储或读取 就行了。抽象可以提高代码的可扩展性和维护性,修改实现不需要改变定义,可以减少代码的改动范围。
LocalStorage
如果接下来我们有一个需求,我们进行一个MySQL的存储【模拟】,那我们怎么扩展我们的代码呢?
// MySqlStorage类实现IStroage接口class MySqlStorage implements IStorage { save(key: string, value: any): void { // mysql.setItem(key,value); } read(key: string) { // return mysql.getItem(key); }}let mysqlStorage = new MySqlStorage();let mysql = new UserInfo('mysql',mysqlStorage);我们只需要定义一个
MySqlStorage
类实现即可,不用去改动UserInfo
类的定义。
调用者和功能实现之间耦合度降低,调用者不需要知道怎么功能实现,改了功能也不用去通知调用者或者修改调用者,这就是抽象。
概念:
实现:
代码展示:
class Animal { // 公有:此属性可以在本类,子类和其他类中访问 public name: string; // 受保护的:此属性可以在本类和子类中访问,其他类不行 protected age: number; // 私有:此属性只能在本类中访问,子类和其他类都不行。 private weight: number; constructor(name: string, age: number, weight: number) { this.name = name; this.age = age; this.weight = weight; }}class Person extends Animal { // 账户余额 私有的,只有自己可以访问 private balance: number; constructor(name: string, age: number, weight: number, balance: number) { super(name, age, weight); this.balance = balance; } getName() { return this.name; } getAge() { return this.age; } getWeight() { return this.weight; // weight私有,无法访问 }}let p1 = new Person('zhufeng', 10, 100, 1000);p1.name;p1.age; // age受保护,不可访问p1.weight; // weight私有,不可访问
代码解释:
上面封装的都是以 属性 来举例,对于类内部的方法来说同样可以用修饰符修饰。
封装的概念较为简单,有代码做理解,这里就不过多赘述了。
概念:
继承主要的用处是实现代码复用。
继承可以把父类和子类的公共方法抽象出来,提高复用,减少冗余。
缺点:
代码展示:
class Animal { public name: string; constructor(){ this.name = name; } eat(){ console.log('吃东西'); }}let animal = new Animal();animal.eat();class Dog extends Animal { }let dog = new Dog();dog.eat();
代码解释:
**题外话:**现在我们一般用的框架,例如:Angular,组件之间也是可以继承的,感兴趣的同学可以尝试尝试组件之间的继承。
概念:
代码展示:
class Animal { speak() { throw new Error('此方法必须由子类实现'); }}// 子类必须实现speak方法,不实现就报错class Dog extends Animal { speak() { console.log('汪汪汪'); }}class Cat extends Animal { speak() { console.log('喵喵喵'); }}function talk(animal: Animal) { animal.speak();}talk(new Dog()); //汪汪汪talk(new Cat()); //喵喵喵
代码解释:
Cat类和Dog类都集成了Animal类,同时也都重写了Animal类的speak方法。
子类对父类的方法重写是必须的,不重写就会出错。
这种情况下,其实Animal类还有另一种写法,使用abstract
关键字【抽象类】:
abstract class Animal { abstract speak(): void;}
对于父类的方法,子类可以有各种各样的实现,这就是多态。
转载地址:http://fldmz.baihongyu.com/