Skip to content
本站總訪問量
本站訪客數 人次

物件導向 OOP 以 JavaScript 為例

創建 Class

js
// 宣告類別
class Animal {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  getInfo() {
    return `Name: ${this.name}, Age: ${this.age}`;
  }
}

使用 Class

使用new關鍵字並傳入建立的動物對象的給定名稱和年齡。有一個 getInfo 方法,用於傳回有關物件的信息

js
// 使用類別
const firstAnimal = new Animal("Rex", 2);
console.log(firstAnimal);               // Animal { name: 'Rex', age: 2 }
console.log(firstAnimal.getInfo());     // Name: Rex, Age: 2

const secondAnimal = new Animal("Barney", 5);
console.log(secondAnimal);              // Animal { name: 'Barney', age: 5 }
console.log(secondAnimal.getInfo());    // Name: Barney, Age: 5

繼承

繼承是類別的一種功能,它使芋些類別能夠獲取另一個類別(父類別)的所有方法和屬性,並可以透過添加更多內容來擴展父類。

js
// 宣告類別
class Dog extends Animal {
  constructor(name, age, breed) {
    super(name, age);
    this.breed = breed;
  }

  bark() {
    return "woof";
  }
}

class Cat extends Animal {
  constructor(name, age, weight) {
    super(name, age);
    this.weight = weight
  }
}

// 使用類別
const myDog = new Dog("Buddy", 2, "Golden Retriever");
console.log(myDog.getInfo());         // Name: Buddy, Age: 2
console.log(myDog.bark());            // woof

const myCat = new Cat("Fluffy", 3, "5kg");
console.log(myCat.getInfo());         // Name: Fluffy, Age: 3

封裝

封裝是一種限制機制,使得訪問不使用特殊方法不可能獲得的數據致力於此。在下面的例子中我們標記了權重作為私有財產,為了獲取和設定一個值,我們需要使用 getter 和 setter 方法

js
// 宣告類別
class Cat extends Animal {
  #weight;                  // ------------> 創造私有值
  constructor(name, age, weight) {
    super(name, age);
    this.#weight = weight;
    this.weight = weight;
  }

  getWeight() {             // ------------> getter
    return this.#weight;
  }

  setWeight(weight) {       // ------------> setter
    this.#weight = weight;
  }
}

// 使用類別
const myCat = new Cat("Fluffy", 3, "5kg");
console.log(myCat.getWeight());         // 5kg
myCat.setWeight("6kg");
console.log(myCat.getWeight());         // 6kg

多型

多型性是利用繼承來重複使用的概念,根據類別的不同,多次使用不同行為的方法類型。

為了理解這一點,讓我們來看看我們的例子——在狗類中我們將刪除bark()方法,並在動物類中添加一個makeSound方法將被貓和狗類覆蓋

js
// 宣告類別
class Animal {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  makeSound() {
    return "Some nice sound made";
  }
}

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

  makeSound() {
    return "woof";
  }
}

class Cat extends Animal {
  constructor(name, age, weight) {
    super(name, age);
    this.weight = weight;
  }

  makeSound() {
    return "meow";
  }
}

// 使用類別
const myDog = new Dog("Buddy", 2, "Golden Retriever");
console.log(myDog.makeSound());         // woof

const myCat = new Cat("Fluffy", 3, "5kg");
console.log(myCat.makeSound());         // meow

抽象類別

抽象類別是不能被實例化的類,需要從特定繼承的子類,抽象類別提供實作。

我們將Animal類別變更為抽象類別。它不會可以再建立此類別的實例將makeSound標記為抽象方法 - 為了使用它,子類別必須聲明該方法自己的實現

簡單來說,變成抽象後就不能new Animal了,要用Cat去繼承Animal

js
class Animal {
  constructor(name, age) {
    this.name = name;
    this.age = age;
    if (this.constructor === Animal) {
      throw new Error("無法建立抽象類別的實例");
    }
  }

  makeSound() {
    throw new Error("必須實作 makeSound 方法");
    return "Some nice sound made";
  }
}

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

  makeSound() {
    return "woof";
  }
}

class Cat extends Animal {
  constructor(name, age, weight) {
    super(name, age);
    this.weight = weight;
  }

  //   makeSound() {
  //     return "meow";
  //   }
  makeSound() {
    return "meow";
  }
}

// const firstAnimal = new Animal("Rex", 2); // Error: 無法建立抽象類別的實例
const myDog = new Dog("Buddy", 2, "Golden Retriever");
const myCat = new Cat("Fluffy", 3, "5kg");
// console.log(myCat.makeSound()); // Error: 必須實作 makeSound 方法

Contributors

The avatar of contributor named as lucashsu95 lucashsu95

Changelog