聊聊TypeScript中類、接口之間相互繼承與實現的那些事兒

本文講述了類的繼承、接口的實現中須要注意的一些小細節,同時也對類、接口的多繼承作了一些講解。app

先看一下繼承

類的繼承

子類繼承了父類以後,就會將父類中定義的非 private 屬性以及方法都繼承下來ui

class Animal {
      public name: string = "Animal";
      public age: number;

      sayHello() {
          console.log(`Hello ${ this.name }`);
      }
  }

  class Dog extends Animal {
      age: number;

      constructor(age) {
          super();
          this.age = age;
      }
  }

  const dog = new  Dog(6);

  dog.sayHello();
複製代碼

因爲 Dog 繼承了 Animal 類,因此同時也繼承了 Animal 的 name 屬性和 sayHello 方法,所以能夠直接使用 dog 實例調用 sayHello 方法。 那麼問題來了:若是能夠進行多繼承,若多個父類中都包含同一個屬性,那麼子類使用的應該是哪一個父類的屬性呢? 所以 TypeScript 中不容許進行多繼承,但是我就是想進行類的多繼承該怎麼辦呢?可使用用下節所說的 Mixins 的方式。this

類的多繼承(Mixins 模擬)

  • 先定義兩個類,Person 和 Student 類
// Person 類
  class Person {
      name: string;
      sayHello() {
          console.log('tag', `Helo ${ this.name }!`)
      }
  }

  // Student 類
  class Student {
      grade: number;

      study() {
          console.log('tag', ' I need Study!')
      }
  }
複製代碼
  • 下面建立一個類,結合 Person 和 Student 這兩個類 首先應該注意到的是,沒使用 extends 而是使用 implements。 把類當成了接口,僅使用 Person 和 Student 的類型而非其實現。 咱們能夠這麼作來達到目的,爲將要mixin進來的屬性方法建立出佔位屬性。 這告訴編譯器這些成員在運行時是可用的。
class SmartObject implements Person, Student {

      // Person
      name: string = 'person';
      sayHello: () => void;
      // Activatable
      grade: number = 3;
      study: () => void;
  }
複製代碼
  • 最後,把mixins混入定義的類,完成所有實現部分
// 把mixins混入定義的類
  applyMixins(SmartObject, [Person, Student]);


  // applyMixins 方法
  function applyMixins(derivedCtor: any, baseCtors: any[]) {
      baseCtors.forEach(baseCtor => {
          Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
              derivedCtor.prototype[name] = baseCtor.prototype[name];
          })
      });
  }
複製代碼

接口與類之間的繼承

接口繼承類的方式以及特色與上面類的繼承和類的多繼承一致。spa

接口與接口之間的多繼承

接口與接口之間是能夠直接進行多繼承的。prototype

  • 先定義兩個接口
// 阿里接口
  interface Ali  {
      pay: () => void
  }

  // 騰訊接口
  interface Tencent {
      game: string
      play: () => void
  }
複製代碼
  • 在定義一個接口繼承 Ali、Tencent 接口
// 本身的接口
  interface Self extends Ali, Tencent {
      name: string
      say: () => void
  }
複製代碼

此時Self 接口就包含了 Ali 和 Tencent 接口中全部的屬性和方法code

  • 驗證一下 用一個類實現 Self 接口,必需要將 Ali、 Tencent、 Self 接口中包含的全部屬性和方法都聲明瞭才能夠,否則會編譯報錯
// 使用 Test 類實現 Self 接口
  class Test implements Self {
      game: string;
      name: string;
      pay() {
          console.log('常常用於支付');
      }
  
      play() {
          console.log('能夠玩各類遊戲');
      }
  
      say() {
          console.log('不知道說點兒什麼');
      }
  }
複製代碼

再來看一下接口的實現

接口的實現

接口在定義的時候,不能初始化屬性以及方法,屬性不能進行初始化,方法不能實現方法體。 類實現接口以後,必須聲明接口中定義的屬性以及方法。繼承

interface Animal {
      name: string;

      eat: () => void;
  }

  class Dog implements Animal {

      name: string;

      eat() {
          console.log('tag', 'I love eat bone!')
      }
  }

  const dog: Dog = new Dog();
  dog.eat();
複製代碼

類對於接口的多實現

一個類能夠實現多個接口,不過要將實現的全部接口的屬性和方法都實現了。接口

// 動物接口
  interface Animal {
      name: string;

      eat: () => void;
  }

  // 貓科接口
  interface Felidae {
      claw: number;
      run: () => void;
  }

  // 讓貓類實現 Animal 和 Felidae 兩個接口
  class Cat implements Animal, Felidae {

      name: string;
      claw: number;

      eat() {
          console.log('tag', 'I love eat Food!');
      }

      run: () {
          console.log('tag', 'My speed is very fast!')
      }
  }

  const dog: Dog = new Dog();
  dog.eat();
複製代碼

總結

  • 類與類之間只能進行單繼承,想要實現多繼承須要使用 Mixins 的方式遊戲

  • 接口繼承類也只能進行單繼承,想要實現多繼承須要使用 Mixins 的方式 Mixins 方式模擬多繼承的缺陷:ip

    • 只能在繼承一級父類的方法和屬性

    • 若是父類中含有同一種方法或屬性,會根據賦值的順序,先賦值的會被覆蓋掉

  • 接口與接口之間能夠直接進行多繼承

  • 類實現接口能夠進行多實現,每一個接口用 , 隔開便可

相關文章
相關標籤/搜索