zoukankan      html  css  js  c++  java
  • Typescript中抽象类与接口详细对比与应用场景介绍

    现如今,TS正在逐渐成为前端OO编程的不二之选,以下是我在学习过程中对抽象类和接口做的横向对比。

    1. 抽象类当做父类,被继承。且抽象类的派生类的构造函数中必须调用super();接口可以当做“子类”继承其他类

    抽象类派生:

    abstract class Human {
        constructor (readonly name:string) {}
        
    }
    
    class Student extends Human {
        constructor (name:string) {
            super(name)
        }
    }

    接口继承类:

    class Man {
        job: string;
        constructor (readonly name: string) {}
        earnMoney () {
            console.log(`earning money`)
        }
    }
    
    interface HumanRule extends Man{
        nose: string;
        mouth: string;
        ear: string;
        eye: string;
        eyebrow: string
    }
    

    当类被接口继承时,通常是需要为这个类的子类添加约束。例如下面的例子中,Man类的子类就需要去实现特定的五官属性,否则将会报错。

    class Player extends Man implements HumanRule{
        nose: string;
        mouth: string;
        ear: string;
        eye: string;
        eyebrow: string
        constructor (name) {
            super(name);
        }
    }
    

    2. 抽象类与接口都无法实例化, 类类型接口实际上是一种 抽象类型

    按个人理解,在使用类类型的接口时,类类型的接口其实就相当于抽象类的子集。抽象类中除了可以像接口那样只定义不实现外,还可以部分实现,而且也可以使用类型修饰符。

    类类型的接口更多的是当做一种抽象的数据类型使用,此处所说的类型通常是某个类的实例类型。

    let James: Player = new Player('james');  // 类类型使用
    
    class SoccerPlayer extends Player {
        constructor (name) {
            super(name)
        }
    
        playSoccer () {
            console.log(`${this.name} is playing soccer.`)
        }
    }
    
    function createPlayer (pl: SoccerPlayer, name: string) {  // 类类型调用
        return new SoccerPlayer(name);
    }

    3. 接口中不能包含具体实现,抽象类中除抽象函数之外,其他函数可以包含具体实现

    此处我们将Human类增加一些内容:

    abstract class Human {
        constructor (readonly name:string) {}
        protected thinking () {
            console.log(`I am a human, so i can think, ${this.name} is thinking.`)
        }
    }

    作为人类,可以在人类 这个类中添加具体实现,因为人类都可以思考。所以思考这个类就不必非要放到子类中去具体实现,这也正是抽象类的灵活之处。

    4. 抽象类中的抽象方法在子类中必须实现, 接口中的非可选项在接口被调用时必须实现。

    此处我们继续增加Human类的内容,增加move的具体实现方法为抽象方法,因为不同类型的人,移动的实现不同。(此处实际上也是OO的特性中,多态的一种具体实现)

    abstract class Human {
        constructor (readonly name:string) {}
        protected thinking () {
            console.log(`I am a human, so i can think, ${this.name} is thinking.`)
        }
        abstract move (): void
    }
    
    class Student extends Human {
        constructor (name:string) {
            super(name)
        }
    
        move () {
            console.log(`I am a student, so i move by bus`)
        }
    }

    而接口一旦调用,就必须要严格实现。此处以函数类型的接口为例:

    interface createPlayer {
        (pl: SoccerPlayer, name:string): SoccerPlayer
    }
    
    let createPlayer:createPlayer = function  (pl: SoccerPlayer, name: string) {  // 修改createPlayer 使用匿名函数方法创建
        return new SoccerPlayer(name);
    }

    5. 抽象方法可当做类的实例方法,添加访问修饰符;但是接口不可以

    抽象方法的添加访问修饰符和接口的严格实现其实都是各自的特点,我们也往往是根据这些特点去选择究竟是使用抽象类还是使用接口。

    还拿Human类来说:

    abstract class Human {
        constructor (readonly name:string) {}
        protected thinking () {
            console.log(`I am a human, so i can think, ${this.name} is thinking.`)
        }
        protected abstract move (): void
    }

    我们为move方法添加abstract标识符,是想让开发者非常明白,Human的派生类中必须要实现此方法;而使用protected标识符,是想限制move方法调用或重载的权限。

    综合来说抽象类更多的是实现业务上的严谨性;接口更多的是制定各种规范,而此规范又分为很多类规范,就像官方文档在介绍接口这一节的时候所说的,例如函数型规范、类类型规范、混合规范、索引规范等。

  • 相关阅读:
    Exception while invoking TaskListener: Exception while invoking TaskListener: null
    oracle mysql gbk varchar varchar2
    WIN10 Samba(SMB) v1 trouble shooting
    信号之信号集
    信号之不可靠的信号及中断的系统调用
    信号之alarm和pause函数
    信号之kill和raise函数
    信号之可靠信号术语和语义
    信号之可重入函数
    信号之signal函数
  • 原文地址:https://www.cnblogs.com/pomelott/p/10480390.html
Copyright © 2011-2022 走看看