首页 > 编程语言 >面向对象编程(2)——封装

面向对象编程(2)——封装

时间:2024-07-28 21:29:47浏览次数:19  
标签:封装 self 接口 面向对象编程 方法 age 属性

目录

一、概念

1.1 主要特点

1.2 实例

二、封装的内容

2.1 属性(数据成员)

2.2 方法(成员函数)

2.3 实现细节

2.4 类的依赖关系

2.5 示例

2.5.1 示例

2.5.2 解释

三、原则与注意事项

3.1 封装的原则

3.2 注意事项


一、概念

        封装(Encapsulation)是面向对象编程中的一个重要概念,它指的是将数据和操作这些数据的方法封装在一个类中,对外部隐藏类的内部实现细节,只有通过类提供的接口(方法)才能访问和修改这些数据。这种机制有助于保护数据的完整性和安全性,同时提高代码的可维护性和灵活性。

1.1 主要特点

  • 数据隐藏:通过将类的属性设置为私有(private),防止外部直接访问和修改这些属性。外部代码只能通过公共(public)的方法来访问这些属性。这有助于避免数据的不一致和意外修改。
  • 接口控制:类提供公共方法作为接口,控制外部如何与内部数据进行交互。这些方法通常被称为“访问器”(getter)和“修改器”(setter)。通过这些方法,可以在访问或修改数据时加入必要的逻辑,如验证输入值或触发某些操作。
  • 提高代码的可维护性:封装使得类的内部实现细节可以随时更改而不影响外部代码。这意味着开发者可以修改或优化类的内部代码,而不需要修改依赖于该类的外部代码。

1.2 实例

        以下是一个简单的封装示例,用于表示一个人的类。该类封装了人的姓名和年龄属性,并通过公共方法来访问和修改这些属性。

class Person:
    def __init__(self, name, age):
        self.__name = name   # 私有属性
        self.__age = age     # 私有属性

    # 访问器方法
    def get_name(self):
        return self.__name

    def get_age(self):
        return self.__age

    # 修改器方法
    def set_name(self, name):
        if isinstance(name, str):
            self.__name = name
        else:
            raise ValueError("Name must be a string")

    def set_age(self, age):
        if isinstance(age, int) and age > 0:
            self.__age = age
        else:
            raise ValueError("Age must be a positive integer")

        在这个例子中,__name__age是私有属性,它们只能通过类的内部方法访问。公共方法get_nameget_ageset_nameset_age提供了访问和修改这些私有属性的方式,并在需要时进行数据验证。这样可以确保属性值始终处于有效状态。

二、封装的内容

        在面向对象编程中,封装的内容可以包括数据、行为和实现细节等方面。具体而言,以下内容通常会被封装:

2.1 属性(数据成员)

        属性是类的内部数据,它们代表对象的状态或特征。封装属性的目的是防止外部代码直接访问和修改这些数据,以保护数据的完整性和一致性。

  • 私有属性:通过使用特定的命名约定(如在属性名前加下划线 _ 或使用双下划线 __)将属性标记为私有,这样可以限制对这些属性的直接访问。
  • 访问控制:通过访问器(getter)和修改器(setter)方法来控制属性的读取和修改,从而确保数据的一致性和有效性。

2.2 方法(成员函数)

        方法是类的行为,它们定义了类可以执行的操作。封装方法有助于限制外部对类的行为的直接控制,并可以在方法内部添加额外的逻辑。

  • 私有方法:同样可以使用特定的命名约定将方法标记为私有,以防止外部直接调用。这些私有方法通常用于内部实现细节,而不希望被外部使用。
  • 公共方法:这些是类对外提供的接口,定义了如何与类交互。公共方法应简洁明了,隐藏实现细节,仅暴露必要的功能。

2.3 实现细节

        封装不仅限于数据和方法,还包括类的内部实现细节。封装实现细节有助于保护类的内部结构,使其可以在不影响外部接口的情况下进行修改和优化。

  • 算法和逻辑:类中的算法和逻辑实现应被封装,以防止外部依赖于这些具体实现。这使得类的内部实现可以随着需求的变化而调整,而不会破坏依赖该类的其他部分。
  • 内部数据结构:类可能使用一些内部数据结构来实现其功能。这些数据结构不应被暴露给外部,以防止外部代码对其进行不当操作。

2.4 类的依赖关系

        封装还可以涵盖类之间的依赖关系和协作细节。通过接口或抽象类定义依赖,可以使具体实现对外部代码不可见,增强系统的灵活性和可扩展性。

2.5 示例

2.5.1 示例

        我们将创建一个简单的银行账户类 BankAccount,该类封装了账户的基本信息和操作,如存款、取款和查询余额。

class BankAccount:
    def __init__(self, account_number, account_holder, initial_balance=0):
        self.__account_number = account_number   # 私有属性:账户号码
        self.__account_holder = account_holder   # 私有属性:账户持有人
        self.__balance = initial_balance         # 私有属性:账户余额

    def deposit(self, amount):
        """存款方法:增加账户余额"""
        if amount > 0:
            self.__balance += amount
            print(f"Deposited {amount}. New balance: {self.__balance}")
        else:
            print("Deposit amount must be positive.")

    def withdraw(self, amount):
        """取款方法:减少账户余额"""
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            print(f"Withdrew {amount}. New balance: {self.__balance}")
        else:
            print("Invalid withdrawal amount.")

    def get_balance(self):
        """获取账户余额方法:返回当前余额"""
        return self.__balance

    def get_account_info(self):
        """获取账户信息方法:返回账户号码和持有人信息"""
        return f"Account Number: {self.__account_number}, Account Holder: {self.__account_holder}"

# 使用例子
account = BankAccount("123456789", "Alice", 1000)
account.deposit(500)        # 输出: Deposited 500. New balance: 1500
account.withdraw(200)       # 输出: Withdrew 200. New balance: 1300
print(account.get_balance())    # 输出: 1300
print(account.get_account_info())  # 输出: Account Number: 123456789, Account Holder: Alice

2.5.2 解释

  1. 数据隐藏和私有属性

    • __account_number__account_holder__balance 这些属性使用双下划线开头,表示它们是私有属性,不应被类的外部直接访问。这样做保护了账户信息的安全,防止外部修改这些重要数据。
  2. 公共方法

    • depositwithdraw 方法提供了修改账户余额的功能,但这些修改是通过控制逻辑(如检查金额是否为正数或账户余额是否足够)来保护数据的完整性。
    • get_balance 方法提供了一个安全的方式来查询账户余额,而不直接暴露余额数据。
    • get_account_info 方法允许访问账户的基本信息,但也隐藏了更多的细节,如账户余额。
  3. 封装的好处

    • 通过这些封装,类的使用者无需了解内部实现细节,只需要使用类提供的公共方法即可操作账户。
    • 如果将来需要修改存款或取款的实现(例如添加手续费计算),可以直接修改类内部的方法,而不影响使用这些方法的代码。

三、原则与注意事项

        封装是面向对象编程中的一个重要原则,它有助于保护数据、简化接口、提高代码的可维护性和可扩展性。在实践中,封装需要遵循一些原则和注意事项,以确保其有效性。

3.1 封装的原则

  1. 数据隐藏:尽可能将类的内部数据(属性)设置为私有,外部代码不应直接访问这些属性。可以使用访问器(getter)和修改器(setter)方法来控制数据的访问和修改。
  2. 明确的接口:为类提供清晰、简洁的公共方法(接口),使得外部代码可以通过这些方法与类交互。这些方法应该对类的行为进行封装,而不是暴露类的内部实现细节。
  3. 职责单一:一个类应该有明确的职责,不应该承担与其主要功能无关的任务。这样有助于保持类的简洁和专注。
  4. 接口分离:将不同的功能分割到不同的接口中,使得类只需要实现它们所需的接口。这有助于减少类之间的耦合,提高系统的灵活性。
  5. 最小暴露:只暴露必要的接口和数据。避免将类的内部实现细节暴露给外部,以减少对实现细节的依赖。

3.2 注意事项

  1. 合理使用访问器和修改器:尽管访问器和修改器方法是封装的一部分,但不应滥用它们。如果属性的直接访问不需要任何逻辑处理,过度使用这些方法可能导致不必要的代码复杂性。
  2. 避免暴露内部数据结构:不要通过公共方法直接返回类的内部数据结构,如列表、字典等。如果确实需要返回这些数据,应返回其副本或使用不可变对象,以防止外部代码对其进行修改。
  3. 保持接口稳定:接口是外部代码与类交互的主要方式,因此应尽量保持接口的稳定。修改接口可能导致依赖这些接口的代码需要修改,从而引发维护上的问题。
  4. 文档化:清晰的文档有助于外部开发者理解类的功能和使用方法。应详细说明每个公共方法的用途、参数、返回值以及可能的副作用。
  5. 考虑性能和安全性:封装不仅是为了保护数据的完整性,还可以在方法中添加额外的逻辑以提高系统的安全性和性能,例如输入验证、缓存机制等。

        通过遵循这些原则和注意事项,可以更好地利用封装特性,设计出结构良好、易于维护和扩展的软件系统。

标签:封装,self,接口,面向对象编程,方法,age,属性
From: https://blog.csdn.net/apple_53311083/article/details/140752046

相关文章

  • 模块3 面向对象编程高级 --- 第十一章:异常处理
    第十一章异常处理主要知识点1、异常产生的原因2、标准异常类3、Java的异常处理机制4、异常的创建5、异常的抛出6、异常语句的编程学习目标熟悉异常产生的原因和标准异常类的用法。能够运用异常处理机制编写Java程序,提高安全性;11.1异常的......
  • yii2代码封装
    1、批量更新某个字段/***@throwsCDbException*@throwsCException*updatexxxTablesetcolumn1=casepk*whenwhenData1thencaseData1*...*END*whereidin(1,2,3...)*/publicfunctionbatc......
  • 模块3 面向对象编程高级 --- 第十章:实现多态
    第十章实现多态主要知识点1、多态的定义2、实现多态的条件学习目标理解多态的含义,掌握多态的使用方法,所谓多态:多种状态。在面向对象语言中,接口中定义的抽象方法的多种不同实现方式即多态。10.1创建多态的条件10.1.1多态的定义首先多态的作用是什么呢?......
  • 使用vite创建react项目并进行初始化(仓库、路由、封装)
    前言学的时候都是跟着教程进行创建,后面发现自己写项目的时候记不住需要做什么,所以现在写一篇来给自己总结一下。(后面忘了也不用翻视频了,直接照着抄答案)只写流程,没有理论。这是我写的习惯,只具备一定通用性,有需要可参考。创建项目npmcreatevite@latestHireSpherenpmins......
  • 模块3 面向对象编程高级 --- 第八章:实现继承
    第八章实现继承主要知识点1、继承的概念2、继承的实现3、用this和super关键字实现继承4、抽象类的实现学习目标掌握继承和抽象类的定义和实现方法。借助集成,可以扩展原有的代码,应用到其他程序中,而不必要重新编写这些代码。扩展声明的新类称为子类,原有......
  • Python 中的面向对象编程
    一.介绍在本文中,我们将使用Python中的类和对象来探索基本的OOP概念。面向对象编程(OOP)是一种强大的方法,可帮助开发人员组织代码,使其易于理解、重用和维护。Python是一种灵活的语言,可以很好地支持OOP概念。1.类和对象类是创建对象的蓝图。它定义了该类的对象将......
  • 使用pybind11封装c++的dll,供python调用
    用pip安装好pybind11 文件清单,都写在一个目录里//文件名:add.cppextern"C"doubleadd(doublein1,doublein2){returnin1+in2;}//文件名:sub.cppextern"C"doublesub(doublein1,doublein2){returnin1-in2;}//文件名:mul.cppextern"......
  • 一文彻底搞懂浏览器事件机制、事件委托、事件冒泡、事件循环、Event Loop、react事件
    一、事件是什么?事件模型?事件是用户操作网页时发生的交互动作,比如click/move,事件除了用户触发的动作外,还可以是文档加载,窗口滚动和大小调整。事件被封装成一个event对象,包含了该事件发生时的所有相关信息(event的属性)以及可以对事件进行的操作(event的方法)。事件是用......
  • 异步操作的华尔兹,Promise详解,在ArkTs如何正确使用?如何使用Promise去封装Sqlite数据库
    目录1.什么是Promise2.Promise中的基本概念3.理解Promise4.Promise的重要方法5.实战我们可以使用Promise去封装一个Splite1.什么是PromisePromise是一种用于异步编程的模式,它提供了一种优雅的方式来处理异步操作的结果,避免了回调地狱问题。在Promise中,每一个Promis......
  • 模块3 面向对象编程高级 --- 第九章:实现接口
    第九章实现接口主要知识点1、接口的定义2、接口的声明3、接口的实现4、接口的应用学习目标掌握接口的定义、声明、实现以及使用方法。接口是一种特殊的类,允许包括变量、常量等一个类所包含的基本内容,可以包含方法。接口中的方法只能有声明,不允许......