JavaScript 中使用 OOP 要遵循的 3 条原则

315 阅读2分钟

简单来说,OOP 是什么?

首先,OOP 代表“面向对象编程”。OOP 是使用“对象”来表示数据并与之交互的思想。

在 OOP 中管理数据时,我们可以利用作为“类”实例的对象,这意味着创建对象并在其中包含属性和方法的蓝图。

类对象是可重用的,能够继承属性和方法,并允许保留相同的方法但遵循多态性的思想以不同的方式执行它们。

在 OOP 中使用类可以优化代码结构,从而提高代码的模块化和可读性。

为了更加理解OOP的逻辑,让我们进入本文的正题;OOP 的 3 大原则——封装、继承和多态!

1.封装

封装代表创建一个胶囊,将属性和方法保存在内部,以保护它们免受来自外部的意外访问。

封装允许我们使代码结构简单易维护,以保持代码的良好可维护性。

它还使我们能够在不将代码暴露在类之外的情况下实现代码,从而防止错误和错误。

这是描述封装的简单代码示例。

// Declare a class whose name is Fruit
class Fruit {
  name: string;
  color: string;

  // Initialize properties of Fruit class
  constructor(name: string, color: string) {
    this.name = name;
    this.color = color
  }

  // Declare a describeFruit method
  describeFruit() {
    console.log(`The color of ${this.name} is ${this.color}.`);
  }
}

const apple = new Fruit("Apple","red")

// We can access and implement properties and methods capsuled in Fruit class
console.log(apple.color) // Output: "red"
apple.describeFruit() // Output: "The color of Apple is red."

// When trying to access non-existing instances, TypeScript complains that and gives us an error 
console.log(apple.size) // Error: Property 'size' does not exist on type 'Fruit'.

2.继承

OOP 中的继承是指创建新类的过程,这些新类从现有类继承一个或多个属性和方法。

继承有助于减少代码行,因为我们根本不必在每次继承父类的新值时都编写重复的代码。

这是用于解释继承的代码片段。

// Declare Parent class
class Parent {
    firstName: string;
    lastName: string;
    age: number;

    constructor(firstName: string, lastName: string, age: number) {
        this.firstName = firstName
        this.lastName = lastName
        this.age = age
    }
    greeting() {
        console.log(`Hi, my name is ${this.firstName} ${this.lastName}, and I'm ${this.age} years old!`)
    }
}

// Define Child class that inherits Parent class
class Child extends Parent {
    // Type definition for the property that does not exist in Parent class
    isAbleToDrink: boolean

  constructor(firstName: string, lastName: string, age: number, isAbleToDrink: boolean) {
        // super is a special keyword referring to instances that extended class has
        super(firstName, lastName, age);
        this.isAbleToDrink = isAbleToDrink;
    }
    buyBeverage() {
        console.log(this.isAbleToDrink ? `${this.firstName} can buy a Coke` : `${this.firstName} can a glass of beer`)
    }
}

const dad = new Parent("Mike", "Trout",32)
console.log(dad.age) // Output: 32
dad.greeting() // Output: "Hi, my name is Mike Trout, and I'm 32 years old!"

const son = new Child('John', 'Trout',12, false);
console.log(son.isAbleToDrink) // Output: false

// Thanks to inheritance, we can access the method that is defined in Parent class
son.greeting() // Output: "Hi, my name is John Trout, and I'm 12 years old!"
son.buyBeverage() // Output: "John can buy a Coke"

3.多态性

多态性是允许对象分别采用多种不同形式的特性。

换句话说,从父类继承方法的子类仍然可以以相同的名称但不同地实现它们。

这个原则允许我们在子类中有一些灵活性,特别是方法的结果取决于分别在它们中编写的代码。

下面的代码示例说明了 saySomthing 方法中多态性的概念。

// Declare Animal class as the parent class
class Animal {
  nickname:string;

  constructor(nickname:string) {
    this.nickname = nickname;
  }

  saySomething() {
    console.log(`${this.nickname} says something.`);
  }
}

// Each sub class (Dog, Cat, and Cow) has same method (saySomething) as Animal class has but outputs from it are different respectively
class Dog extends Animal {
  saySomething() {
    console.log(`${this.nickname} barks.`);
  }
}

class Cat extends Animal {
  saySomething() {
    console.log(`${this.nickname} meows.`);
  }
}

class Cow extends Animal {
  saySomething() {
    console.log(`${this.nickname} moos.`);
  }
}

new Dog("Zoy").saySomething() // Output: "Zoy barks."
new Cat("Mike").saySomething() // Output: "Mike meows."
new Cow("John").saySomething() // Output: "John moos."

结论

OOP 的 3 个概念(封装、继承和多态)对于提高您对 JavaScript(以及其他面向对象编程语言)中的类的理解以及通过应用 JavaScript 类来增强代码性能绝对至关重要。