繼承

繼承 在 JavaScript

1 個練習

關於 繼承

繼承是一種在類別之間建立親子關係的方式。 子類別(有時稱為 subclass)可以存取父類別(有時稱為 superclass)所定義的行為與資料。

class Pet {
  constructor(name) {
    this.name = name;
  }

  introduce() {
    console.log(`This is my pet, ${this.name}.`);
  }
}

class Dog extends Pet {}

const dog = new Dog('Otis');
dog.introduce();
// => This is my pet, Otis.

子類別宣告中的extends關鍵字會透過原型鏈與父類別建立關係。

由子類別建構函式建立的物件,其原型鏈中會包含父類別的原型,因此可以存取父類別所定義的任何方法或資料。

const dog = new Dog('Otis');

Dog.prototype.isPrototypeOf(dog); // => true
Pet.prototype.isPrototypeOf(dog); // => true
Pet.prototype.isPrototypeOf(Dog.prototype); // => true

Pet.prototype.hasOwnProperty('introduce'); // => true
Dog.prototype.hasOwnProperty('introduce'); // => false
dog.hasOwnProperty('introduce'); // => false

建構函式

如果子類別沒有定義建構函式,就會使用父類別的建構函式。 不過,如果子類別定義了自己的建構函式,就必須明確呼叫父類別的建構函式。 若要從子類別建構函式的作用域中呼叫父類別的建構函式,需使用super關鍵字。

class Pet {
  constructor(name) {
    this.name = name;
  }
}

class Dog extends Pet {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }
}

const dog = new Dog('Otis', 'Pug');

由於父類別的建構函式負責初始化新的物件並將其指定給this,因此必須在子類別建構函式使用this之前先呼叫它。

class Dog extends Pet {
  constructor(name, breed) {
    // using 'this' before calling the parent constructor with 'super'
    this.breed = breed;
    super(name);
  }
}

const dog = new Dog('Otis', 'Pug');
// => ReferenceError: Must call super constructor in derived class before accessing 'this'...

在子類別上定義方法

子類別除了繼承自父類別的行為之外,也可以定義自己的行為。

這是使用繼承的關鍵原因之一:讓特化的子類別擁有自己獨特的資料與方法,並透過父類別所提供的共用方法與資料彼此產生關聯。

class Dog extends Pet {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  describe() {
    console.log(`${this.name} is a ${this.breed}.`);
  }
}

const dog = new Dog('Otis', 'Pug');
dog.introduce();
dog.describe();
// => 'This is my pet, Otis.'
// => 'Otis is a Pug.'

覆寫繼承自父類別的方法

子類別也可以覆寫父類別所定義方法的行為,並以子類別定義的行為來取代或擴充它。

class Cat extends Pet {
  // replacing parent class behavior
  introduce() {
    console.log(`This is my cat, ${this.name}.`);
  }
}

class Dog extends Pet {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  describe() {
    console.log(`${this.name} is a ${this.breed}.`);
  }

  // extending parent class behavior
  introduce() {
    super.introduce();
    this.describe();
  }
}

const cat = new Cat('Milo');
cat.introduce();
// => 'This is my cat, Milo.'

const dog = new Dog('Otis', 'Pug');
dog.introduce();
// => This is my pet, Otis.
// => Otis is a Pug.

若要從子類別中同名方法的內容呼叫父類別所定義的方法,必須使用super關鍵字來參照父類別。

透過 GitHub 編輯 連結會在新視窗或分頁中開啟

學習 繼承