8. 面向对象特征 :封装、继承,多态

8. 面向对象特征 :封装、继承,多态

8.1 封装

8.1.1 封装概念

  • 封装(Encapsulation): 在设计类时,刻意地将一些属性和方法隐藏在类的内部,这样在使用此类时,将无法直接以 类对象.属性名(或者 类对象.方法名(参数))的形式调用这些属性(或方法),而只能用未隐藏的类方法间接操作这些隐藏的属性和方法
  • 封装作用
    • 保证了类内部数据结构的完整性,避免外部对内部数据的影响,提高了程序的可维护性
    • 避免用户对类中属性或方法的不合理操作
    • 提高代码的复用性

8.1.2 封装方法

  • 类中的变量和函数,可分为:公有的(类似 public 属性)和 私有的(类似 private)这 2 种属性 :
    • 公有属性 (public):类变量和类函数,在类的外部、类内部以及子类中都可以正常访问
    • 私有属性(private):类变量和类函数,只能在本类内部使用,类的外部以及子类都无法使用
  • python实现类的封装的方法:
    • 默认情况下,Python 类中的变量和方法都是公有(public)的,它们的名称前都没有下划线_
    • 其名称以双下划线 __ 开头的变量(函数)为私有变量(私有函数),其属性等同于 private
    • 单下划线 _开头的类属性或者类方法,通常被视为私有属性私有方法

注意 :Python 类中还有以双下划线开头和结尾的类方法(例如类的构造函数__init__(self)),这些都是 Python 内部定义的,用于 Python 内部调用,自己定义类属性或者类方法时,不要使用这种格式。

  • 封装底层实现原理
  • 以双下划线开头命名的类属性或类方法,其底层实现封装的原理就是,将它们的名称都偷偷改成了 _类名__属性(方法)名 的格式
  • 因此使用 对象名._类名__属性(方法)名 就可以调用出封装的属性或者方法

8.2 继承

8.2.1 继承基本概念

  • 基本概念
    • 继承机制 :用于创建和现有类功能类似的新类,创建的新类就只需要在现有类基础上添加一些成员(属性和方法),实现类的重复使用
    • 子类 :实现继承的类
    • 父类 :被继承的类(也可称为基类、超类)
    • 继承 :继承是相对子类来说的,即子类继承自父类
    • 派生 :派生是相对于父类来说的,即父类派生出子类
  • 语法格式
class 类名(父类1, 父类2, ...)#类定义部分
  • 特点
    • 多继承机制 :一个子类可以同时拥有多个直接父类
    • 如果类没有显式指定继承自哪个类,则默认继承 object 类(object 类是 Python 中所有类的父类)
    • 子类拥有父类所有的属性和方法,包括私有(private)的属性或方法
    • 当父类中有同名的属性和方法时,子类根据父类的前后次序决定继承那个,即排在前面父类中的类方法会覆盖排在后面父类中的同名类方法(自己编写程序时,尽量不要使用多继承)

8.2.2 多继承机制的继承顺序

  • 继承顺序可分为深度优先广度优先两种机制
  • 如下继承关系 :
    在这里插入图片描述
  • 深度优先的继承顺序 :D - B - A - C
  • 广度优先的继承顺序 :D - B - C - A

8.2.3 父类方法重写

  • 概念
    • 父类方法重写 :继承的父类方法不适用子类时,需要重写该方法
    • 子类重写的方法名和父类一样,根据都继承搜索原则,会先调用子类中的方法
  • 重写方法
class A( ):
	def fun(self):
		pass
class B(A):
	def fun(self):
		pass
cl = B()
cl.fun() # 调用B类中方法fun()
# 假如需要使用A类中的方法fun(),手动传入self值
A.fun(cl) 

8.2.4 super() 调用父类的构造方法

  • 子类中的构造方法中,调用父类构造方法的方式有 2 种 :
    • 类可以看做一个独立空间,在类的外部调用其中的实例方法,可以向调用普通函数那样,只不过需要额外备注类名(此方式又称为未绑定方法
    • 使用 super() 函数,在多继承,该函数只能调用第一个直接父类的构造方法,语法格式 :super().__init__(parm...)
class a() :
	def __init__(self, name) :
		self.name = name
	pass
class b():
	def __init__(self, value) :
		self.value = value
	pass
class c(a, b) :
	def __init__(self, name, value)super().__init__(name) # super()方法
		b.__init__(self, value) # 未绑定方法

8.2.4 类或实例对象添加方法

  • 动态添加方法规则
    • 类添加方法 :python 允许为类动态地添加:实例方法、静态方法和类方法
    • 实例对象添加方法 : 只允许动态地添加实例方法,不能添加类方法和静态方法
    • 单个实例对象添加方法,不会影响该类的其它实例对象
    • 为类动态地添加方法,则所有的实例对象都可以使用
  • 方法实例
class CLanguage:
    pass
def info(self): # 定义了一个实例方法
    pass
@classmethod  
def info2(cls):  #  定义了一个类方法
    pass
@staticmethod
def info3(): # 定义个静态方法
    pass

# 类可以动态添加以上 3 种方法,会影响所有实例对象
CLanguage.info = info
CLanguage.info2 = info2
CLanguage.info3 = info3

clang = CLanguage() # 定义类的实例对象,clang 具有以上 3 种方法
#类实例对象只能动态添加实例方法,不会影响其它实例对象
clang1 = CLanguage()
clang1.info = info
clang1.info(clang1) # 调用必须手动为 self 传值
  • __slots__ 作用即方法
    • 限制为实例对象动态添加属性和方法法,无法限制动态地为类添加属性和方法
    • __slots__ 属性值是一个元组,只有其中指定的元素,才可以作为动态添加的属性或者方法的名称
    • __slots__ 限制的是其方法名,并不限制参数的个数
    • __slots__ 属性对由该类派生出来的子类,也是不起作用的
    • 如下, 以 A 创建的实例对象,只能动态添加 name、add、info 这 3 个属性以及 name()、add() 和 info() 这 3 个方法
class A():
	__slots__ = ('name','add','info')
	pass

8.2.5 动态创建类

  • type() 函数
    • type(obj) : 查看某个变量(类对象)的具体类型
    • type(name, bases, dict) : 用来创建类
      • name 表示类的名称
      • bases 表示一个元组,其中存储的是该类的父类
      • dict 表示一个字典,用于表示类内定义的属性或者方法

8.3 多态

  • 含义
    • 用一个函数名实现调用不同类中的不同内容(功能)的函数方法
  • 特点
    • 只关心对象的实例方法是否同名,不关心对象所属的类型
    • 对象所属的类之间,继承关系可有可无
    • 增加代码的外部调用灵活度,让代码更加通用,兼容性比较强
    • 多态是调用方法的技巧,不会影响到类的内部设计
  • 使用示例
class CLanguage:
    def say(self):
        print("调用的是 Clanguage 类的say方法")
class CPython(CLanguage):
    def say(self):
        print("调用的是 CPython 类的say方法")
class CLinux(CLanguage):
    def say(self):
        print("调用的是 CLinux 类的say方法")
class WhoSay:
    def say(self, who):
        who.say()
a = WhoSay()
a.say(CLanguage())  # 调用 CLanguage 类的 say() 方法
a.say(CPython()) # 调用 CPython 类的 say() 方法
a.say(CLinux()) # 调用 CLinux 类的 say() 方法

感谢阅读 若有错误 敬请见谅 !!!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

园长QwQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值