公告

本次更新:

公告样式,参考自 VuePress-Reco

本博客只技术分享!


Skip to content
本站总访问量
本站访客数 人次
标签
javascriptfacetestgopythonHTML前端CSSvitepress

一、封装

1. 封装的概念

封装是面向对象编程中的一个重要概念,它将数据(属性)和操作数据的方法封装在一起,形成一个独立的对象。封装的主要目的是隐藏内部实现细节,保护数据的安全性,同时提供一个简洁的外部接口。

2. 封装的重要性

  • 对象是一个存储不同属性的容器:对象不仅可以存储数据,还可以通过方法对数据进行操作。
  • 确保数据的安全性:直接添加到对象中的属性可以被任意修改,这可能导致数据的不一致性和安全问题。
  • 封装的作用:通过封装,可以隐藏内部数据的实现细节,只暴露必要的接口,从而保护数据的安全性。

3. 实现封装的方法

3.1 私有化数据

将需要保护的数据设置为私有,只能在类内部使用。在 JavaScript 中,可以通过 # 前缀来定义私有属性。

3.2 提供 gettersetter 方法

通过 gettersetter 方法来操作私有属性,可以控制属性的读写权限,并在方法中对属性的值进行验证。

示例代码
javascript
class Person {
    #name;  // 私有属性

    constructor(name) {
        this.#name = name;
    }

    // Getter 方法
    get name() {
        return this.#name;
    }

    // Setter 方法
    set name(value) {
        if (typeof value === 'string') {
            this.#name = value;
        } else {
            throw new Error('Name must be a string');
        }
    }
}

// 使用
const person = new Person("Alice");
console.log(person.name);  // 输出: Alice
person.name = "Bob";       // 修改属性
console.log(person.name);  // 输出: Bob

3.3 封装的好处

  1. 控制属性的读写权限:通过 gettersetter 方法,可以限制属性的访问权限,只允许在满足特定条件时修改属性。
  2. 数据验证:在 setter 方法中可以对属性的值进行验证,确保数据的合法性。
  3. 隐藏内部实现:将数据和实现细节隐藏在类内部,只暴露必要的接口,减少外部依赖。

4. 封装的实现方式

  • 属性私有化:使用 # 前缀定义私有属性。
  • 通过 gettersetter 方法操作属性
    javascript
    get 属性名() {
        return this.#属性;
    }
    
    set 属性名(参数) {
        this.#属性 = 参数;
    }

通过封装,可以确保数据的安全性,同时提供灵活的接口供外部使用。封装是面向对象编程中的核心概念之一,广泛应用于各种编程语言中。

js
class Person {
    #name;
    #age;
    
    getName(){
        return this.#name;
    }

    setName(name){
        this.#name = name;
    }

    getAge(){
        return this.#age;
    }

    setAge(age){
        this.#age = age;
    }

    constructor(name,age){
        this.#name = name;
        this.#age = age;
    }
    
    sayHello(){
        console.log(this.#name)
    }

}

const p1 = new Person("zs", 18);

console.log(p1);
console.log(p1.getAge());
p1.setAge(11);
console.log(p1.getAge());
p1.sayHello();

以下是关于多态的 Markdown 格式内容,优化了排版和结构,使其更加清晰和优美:


二、 多态

多态的概念

多态是面向对象编程中的一个重要概念,允许你通过不同的方式实现相同的行为。它允许一个接口或方法以不同的底层实现来运行,具体实现取决于对象的实际类型。

多态的特点

  • 动态类型检查:在 JavaScript 中,不会检查参数的类型,这意味着任何数据都可以作为参数传递。
  • 无需指定类型:调用某个函数时,无需指定具体的类型,只要对象满足某些条件即可。
  • 鸭子类型:如果一个东西走路像鸭子,叫起来像鸭子,那么它就是鸭子。这种思想体现了多态的核心——关注行为而非类型。

多态的好处

  • 灵活性:多态提供了代码的灵活性,允许不同的对象在相同的接口下表现出不同的行为。
  • 可扩展性:通过多态,可以轻松地添加新的行为,而无需修改现有的代码结构。

实现多态的方式

在 JavaScript 中,多态通常通过以下方式实现:

1. 方法覆盖(Method Overriding)

通过子类覆盖父类中的方法来实现多态。

示例代码
javascript
// 父类
class Animal {
    makeSound() {
        console.log("Some generic animal sound");
    }
}

// 子类
class Dog extends Animal {
    makeSound() {
        console.log("Woof woof!");
    }
}

// 子类
class Cat extends Animal {
    makeSound() {
        console.log("Meow meow!");
    }
}

// 测试
const myDog = new Dog();
const myCat = new Cat();

myDog.makeSound(); // 输出: Woof woof!
myCat.makeSound(); // 输出: Meow meow!

2. 参数多态(Parameter Polymorphism)

通过检查参数类型或数量来实现类似多态的行为。

示例代码
javascript
function describe(value) {
    if (typeof value === "string") {
        console.log(`The string is "${value}"`);
    } else if (typeof value === "number") {
        console.log(`The number is ${value}`);
    } else {
        console.log("Unknown type");
    }
}

// 测试
describe("Hello");    // 输出: The string is "Hello"
describe(42);          // 输出: The number is 42
describe(true);        // 输出: Unknown type

3. 动态类型检查

通过 instanceoftypeof 等操作符来检查对象的类型,并根据类型执行不同的逻辑。

示例代码
javascript
function processValue(value) {
    if (value instanceof Dog) {
        value.makeSound(); // 调用 Dog 的 makeSound 方法
    } else if (value instanceof Cat) {
        value.makeSound(); // 调用 Cat 的 makeSound 方法
    } else {
        console.log("Unknown type");
    }
}

// 测试
processValue(myDog);   // 输出: Woof woof!
processValue(myCat);   // 输出: Meow meow!

总结

多态是面向对象编程中的一个重要概念,允许你通过不同的方式实现相同的行为。在 JavaScript 中,多态通过方法覆盖、参数多态和动态类型检查来实现。多态提供了代码的灵活性和可扩展性,是现代编程中不可或缺的一部分。


通过这些示例和解释,你可以更好地理解和应用多态的概念。

js
// 父类
class Shape {
    draw() {
        console.log("Drawing a shape");
    }
}

// 子类
class Circle extends Shape {
    draw() {
        console.log("Drawing a circle");
    }
}

// 子类
class Square extends Shape {
    draw() {
        console.log("Drawing a square");
    }
}

// 测试
function drawShape(shape) {
    shape.draw();
}

const myCircle = new Circle();
const mySquare = new Square();

drawShape(myCircle);   // 输出: Drawing a circle
drawShape(mySquare);   // 输出: Drawing a square

以下是关于继承的 Markdown 格式内容,优化了排版和结构,使其更加清晰和优美:


三、 继承

继承的概念

继承是面向对象编程中的一个核心概念,允许一个类(称为子类)继承另一个类(称为父类)的属性和方法。通过继承,可以实现代码的复用和扩展。

继承的特点

  • 使用 extends 关键字:在 JavaScript 中,通过 extends 关键字实现类的继承。
  • 代码复用:当一个类继承另一个类时,子类会自动获得父类的所有属性和方法,就像父类的代码被复制到了子类中一样(简单理解)。
  • 父类和子类:在继承关系中,被继承的类称为父类(或超类),继承的类称为子类。
  • 扩展性:通过继承,可以在不修改父类的前提下对类的功能进行扩展。

继承的好处

  • 减少重复代码:通过继承,可以避免在多个类中重复编写相同的代码。
  • 增强可维护性:父类的修改会自动反映到所有子类中,减少了维护成本。
  • 提高可扩展性:可以在不修改现有代码的基础上,通过继承添加新的功能。

实现继承的方式

在 JavaScript 中,继承通过 extends 关键字和 super 方法实现。

示例代码

父类
javascript
class Animal {
    constructor(name) {
        this.name = name;
    }

    makeSound() {
        console.log(`${this.name} makes a sound.`);
    }
}
子类
javascript
class Dog extends Animal {
    constructor(name, breed) {
        super(name); // 调用父类的构造函数
        this.breed = breed;
    }

    makeSound() {
        console.log(`${this.name} barks.`);
    }

    displayBreed() {
        console.log(`${this.name} is a ${this.breed}.`);
    }
}
测试
javascript
const myDog = new Dog("Buddy", "Golden Retriever");
myDog.makeSound();       // 输出: Buddy barks.
myDog.displayBreed();    // 输出: Buddy is a Golden Retriever.

总结

继承是面向对象编程中的一个重要概念,允许一个类继承另一个类的属性和方法。通过继承,可以减少重复代码,增强代码的可维护性和可扩展性。继承、封装和多态是面向对象编程的三大核心特性,它们共同提供了安全性、扩展性和灵活性。

  • 封装:关注数据的安全性。
  • 继承:关注代码的扩展性。
  • 多态:关注行为的灵活性。

通过这些示例和解释,你可以更好地理解和应用继承的概念。

js
class Animal{
    constructor(name){
        this.name = name
    }

    sayHello(){
        console.log("动物在叫~")
    }
}

class Dog extends Animal{
    
}

class Cat extends Animal{
    
}

class Snake extends Animal{

}

const dog = new Dog("旺财")
const cat = new Cat("汤姆")

dog.sayHello()
cat.sayHello()
console.log(dog)
console.log(cat)
  • 通过继承可以在不修改一个类的情况下对其进行扩展
  • OCP 开闭原则
    • 程序应该对修改关闭,对扩展开放
js
class Animal{
    constructor(name){
        this.name = name
    }

    sayHello(){
        console.log("动物在叫~")
    }
}

class Dog extends Animal{

    // 在子类中,可以通过创建同名方法来重写父类的方法
    sayHello(){
        console.log("汪汪汪")
    }
    
}

class Cat extends Animal{

    // 重写构造函数
    constructor(name, age){
        // 重写构造函数时,构造函数的第一行代码必须为super()
        super(name) // 调用父类的构造函数

        this.age = age

    }
    
    sayHello(){

        // 调用一下父类的sayHello  如果需要就调用
        // super.sayHello() // 在方法中可以使用super来引用父类的方法

        console.log("喵喵喵")
    }
}


const dog = new Dog("旺财")
const cat = new Cat("汤姆", 3)

dog.sayHello()
cat.sayHello()
console.log(dog)
console.log(cat)
本站访客数 人次 本站总访问量