博客
关于我
面向对象四大特征
阅读量:653 次
发布时间:2019-03-15

本文共 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即可。

重点来了:

看了我上面写的概念、代码、解释,你可能还是晕乎乎的。你的问题可能还是:什么是抽象

别急,我们对着概念一步一步来看:

  1. 抽象主要是隐藏方法的实现,让调用者只关心有哪些功能而不是关心功能的实现。

    • 在上面的代码里,很明显,调用者是 UserInfo类,UserInfo类 调用 storage 存储功能时,它需要知道 LocalStorage 怎么实现的吗?它不需要知道,他只需要知道通过 storage打点可以拿到save或read进行存储或读取 就行了。
  2. 抽象可以提高代码的可扩展性和维护性,修改实现不需要改变定义,可以减少代码的改动范围。

    • 这里面的重点句子是:扩展或修改的时候我们只需要改动实现,不需要改变定义。
    • 上面代码中的实现很明显是 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类的定义。

调用者和功能实现之间耦合度降低,调用者不需要知道怎么功能实现,改了功能也不用去通知调用者或者修改调用者,这就是抽象。

二、封装

概念:

  • 把数据封装起来 , 减少耦合,不该外部访问的代码不要让外部访问。
  • 封装利于数据的接口权限管理 。
  • 封装仅暴露有限的必要接口,可以提高类的易用性。

实现:

  • public:共有修饰符,可以在类内或者类外使用public修饰的属性或者行为,默认修饰符。
  • protected:受保护的修饰符,可以在本类和子类中使用protected修饰的属性和行为。
  • private:私有修饰符,只可以在类内部使用private修饰的属性和行为。

代码展示:

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私有,不可访问

代码解释:

上面封装的都是以 属性 来举例,对于类内部的方法来说同样可以用修饰符修饰。

  • Person类继承了Animal类,但是Person无法访问Animal类中的 weight 属性,因为 weight 属性 private 修饰。
  • 我们new 了一个Person的实例,然后去访问 age,我们发现 age 不可访问,因为 protected修饰,protected修饰的属性或方法只能在本类和子类中访问。

封装的概念较为简单,有代码做理解,这里就不过多赘述了。

三、继承

概念:

  • 继承主要的用处是实现代码复用。

  • 继承可以把父类和子类的公共方法抽象出来,提高复用,减少冗余。

    缺点:

    • 过度使用继承或者说继承层次过深会导致代码可读性变差,可维护性变差,子类和父类高度耦合,修改父类的代码会直接影响到子类。

代码展示:

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();

代码解释:

  • Dog类继承自Animal类,Dog也就拥有了Animal类所有的方法和属性。
  • 说到这里,我们可能就要联系一下另外一个特征:面向对象——封装 了,这个可以自己体会一下。

**题外话:**现在我们一般用的框架,例如: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/

你可能感兴趣的文章
MyPython
查看>>
MTD技术介绍
查看>>
MySQL
查看>>
MySQL
查看>>
mysql
查看>>
MTK Android 如何获取系统权限
查看>>
MySQL - 4种基本索引、聚簇索引和非聚索引、索引失效情况、SQL 优化
查看>>
MySQL - ERROR 1406
查看>>
mysql - 视图
查看>>
MySQL - 解读MySQL事务与锁机制
查看>>
MTTR、MTBF、MTTF的大白话理解
查看>>
mt_rand
查看>>
mysql -存储过程
查看>>
mysql /*! 50100 ... */ 条件编译
查看>>
mudbox卸载/完美解决安装失败/如何彻底卸载清除干净mudbox各种残留注册表和文件的方法...
查看>>
mysql 1264_关于mysql 出现 1264 Out of range value for column 错误的解决办法
查看>>
mysql 1593_Linux高可用(HA)之MySQL主从复制中出现1593错误码的低级错误
查看>>
mysql 5.6 修改端口_mysql5.6.24怎么修改端口号
查看>>
MySQL 8.0 恢复孤立文件每表ibd文件
查看>>
MySQL 8.0开始Group by不再排序
查看>>