别院牧志知识库 别院牧志知识库
首页
  • 基础

    • 全栈之路
    • 😎Awesome资源
  • 进阶

    • Python 工匠系列
    • 高阶知识点
  • 指南教程

    • Socket 编程
    • 异步编程
    • PEP 系列
  • 面试

    • Python 面试题
    • 2022 面试记录
    • 2021 面试记录
    • 2020 面试记录
    • 2019 面试记录
    • 数据库索引原理
  • 基金

    • 基金知识
    • 基金经理
  • 细读经典

    • 德隆-三个知道
    • 孔曼子-摊大饼理论
    • 配置者说-躺赢之路
    • 资水-建立自己的投资体系
    • 反脆弱
  • Git 参考手册
  • 提问的智慧
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
首页
  • 基础

    • 全栈之路
    • 😎Awesome资源
  • 进阶

    • Python 工匠系列
    • 高阶知识点
  • 指南教程

    • Socket 编程
    • 异步编程
    • PEP 系列
  • 面试

    • Python 面试题
    • 2022 面试记录
    • 2021 面试记录
    • 2020 面试记录
    • 2019 面试记录
    • 数据库索引原理
  • 基金

    • 基金知识
    • 基金经理
  • 细读经典

    • 德隆-三个知道
    • 孔曼子-摊大饼理论
    • 配置者说-躺赢之路
    • 资水-建立自己的投资体系
    • 反脆弱
  • Git 参考手册
  • 提问的智慧
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 辨析

  • Sockets编程

  • Django

  • stackoverflow

  • Flask

  • 全栈之路

  • 面试

  • 代码片段

  • 异步编程

  • 😎Awesome资源

  • PEP

  • Python工匠系列

  • 高阶知识点

  • Python 学习资源待整理
  • 设计模式

  • 好“艹蛋”的 Python 呀!
  • FIFO | 待学清单📝
  • pip 安装及使用
  • 数据分析

  • 源码阅读计划

  • OOP

    • 面向对象之封装、继承、多态
      • 封装
      • 继承
        • 继承的作用
        • 单继承
        • 多继承
        • 私有化
      • 多态
        • 多态的好处
      • 继承与多态的区别
      • 参考链接
  • 关于 python 中的 setup.py
  • 并行分布式框架 Celery
  • 七种武器,让你的代码提高可维护性
  • 使用 pdb 调试 Python 代码
  • 每周一个 Python 标准库
  • 🐍Python
  • OOP
佚名
2022-03-25
目录

面向对象之封装、继承、多态

面向对象的三个基本特征是:封装、继承、多态。

# 封装

封装是面向对象的特征之一,是对象和类概念的主要特性。

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

# 继承

面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

通过继承创建的新类称为“子类”或“派生类”;被继承的类称为“基类”、“父类”或“超类”。

继承的过程,就是从一般到特殊的过程。

# 继承的作用

简化了代码,减少了冗余。继承简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系,提高了代码的健壮性,安全性。

继承是在一些比较一般的类的基础上构造、建立和扩充新类的最有效的手段。

要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。

在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Cat 类却不能继承 Person 类,因为猫并不是一个人。

# 单继承

class Person(object):
    
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
    @staticmethod    
    def run():
        print("run")
        
    def eat(self,food):
        print("eat "+food)
        self.run()


class Student(Person):
    
    def study(self):
        print('I can study.')
        
        
class Employee(Person):
    
    def work(self):
        print('I can work.')

a = Student("wangming",18)
print(a.name)
a.run()
a.eat("orange")

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 多继承

class Immortal:
    def fly(self):
        print('神仙会飞')


class Monkey:
    
    def eat_peach(self):
        print('猴子喜欢吃桃')

class Wukong(Immortal,Monkey):
    pass

swk = Wukong()
swk.fly()
swk.eat_peach()


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 私有化

# 私有属性

以__开头,声明为属性私有,不能在类的外部被使用或者直接访问。

## 私有属性 以__开头,声明为属性私有,不能在类的外部被使用或者直接访问。

class Person(object):
    def __init__(self):
        self.__name = '我叫詹躲躲' ## 私有化
        self.age = '21'

    def __str__(self):
        return '{}的年龄是{}'.format(self.__name,self.age)

person = Person()
## print(person.__name) #报错
print(person) #可以访问
## 我叫詹躲躲的年龄是21

## 私有属性,不能被子类继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 私有方法

class A(object):
    def __eat(self):
        print('吃饭')

    def run(self):
        print('跑步')

b = A()
b.__eat() ## 报错
b.run() ## 跑步

1
2
3
4
5
6
7
8
9
10
11

OO 开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。

# 多态

多态性(polymorphism)是允许你将父对象设置成为和一个或更多的它的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。同一操作作用与不同类的实例,将产生不同的执行结果,即不同类的对象收到相同的消息时,将得到不同的结果。

实现多态的三个必要条件:

  1. 继承
  2. 重写
  3. 父类引用指向子类对象

通俗来讲就是同一个函数,因为传递的参数列表不同,可以实现的不同的功能。

实现多态,有两种方式,覆盖,重载。

覆盖,是指子类重新定义父类的虚函数的做法。

重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

其实,重载的概念并不属于“面向对象编程”,重载的实现是:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;和 function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的(记住:是静态)。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!真正和多态相关的是“覆盖”。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态(记住:是动态!)的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚邦定)。结论就是:重载只是一种语言特性,与多态无关,与面向对象也无关!引用一句 Bruce Eckel 的话:“不要犯傻,如果它不是晚绑定,它就不是多态。”

那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

# 多态的好处

  1. 增加程序的灵活性
  2. 增加程序的扩展性

可以增强程序的可扩展性及可维护性,使代码更加简洁。不但能减少编码的工作量,也能大大提高程序的可维护性及可扩展性。

# 继承与多态的区别

  • 什么是继承,继承的特点?

子类继承父类的特征和行为,使得子类具有父类的各种属性和方法。或子类从父类继承方法,使得子类具有父类相同的行为。

特点:在继承关系中,父类更通用、子类更具体。父类具有更一般的特征和行为,而子类除了具有父类的特征和行为,还具有一些自己特殊的特征和行为。

在继承关系中。父类和子类需要满足 is-a 的关系。子类是父类。

  • 为什么需要继承?什么时候应该继承?

使用继承可以有效实现代码复用,避免重复代码的出现。

当两个类具有相同的特征(属性)和行为(方法)时,可以将相同的部分抽取出来放到一个类中作为父类,其它两个类继承这个父类。

继承实现了面向对象的原则:write once,only once(编写一次、且编写一次

  • 如何实现继承?

在父类中只定义一些通用的属性和方法。

子类自动继承父类的属性和方法,子类中可以定义特定的属性和方法。或子类重新定义父类的属性、重写父类的方法可以获得与父类不同的功能。

  • 什么是方法重写?

如果在子类中定义的一个方法,其名称、返回类型及参数列表正好与父类中某个方法的名称、返回类型及参数列表相匹配,那么可以说,子类的方法重写了父类的方法。

#重写了bark
class Animal: #父类
    def eat(self):
        print("-----吃-----")

    def drink(self):
        print("-----喝-----")

 
class Dog(Animal): 
    def bark(self):
        print("-----汪汪叫------")


class XTQ(Dog): #重写Dog方法
    """定义了一个哮天犬 类"""
    def bark(self):
        print("----嗷嗷叫-----")

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

方法重写在不同类,是实现多态的必要条件。

  • super 关键字的用法和位置,super 关键字调用父类的构造方法,super 关键字调用父类的方法?

在子类的构造方法中,通过 super 关键字调用父类的构造方法。

如果子类中重写了父类的方法,可以通过 super 关键字调用父类的方法。

class PersonalInformation():
    platform = 'python外卖平台'
    
    def __init__(self, name, addr, tel):
        self.name = name  
        self.addr = addr 
        self.tel = tel 
        
# 商家类
class Merchants(PersonalInformation):
    
    def __init__(self, name, addr, tel, food_info):
        super().__init__(name, addr, tel)  # 调用的是绑定方法,自动传入self
        # super(Merchants, self).__init__(name, addr, tel)  # 与上一行代码等价,在python2中必须这么写,python3可以简写
        self.food_info = food_info 
        
    def receive_order(self):
        print(f'{self.name}已经接单')

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

注意:创建对象时,先创建父类对象,在创建子类对象。如果没有显示调用父类的构造方法,将自动调用父类的无参构造方法。

  • 一切类的老大(祖先)Object。

所有类都直接或者间接地继承了 object 类,object 类中定义了所有对象都具有的相同行为,是所有类的祖先。

一个类如果没有显式继承,那么这个类直接继承自 Object 类。

  • 什么是多态?

多态的特征是表现出多种形态,具有多种实现方式。或者多态是具有表现多种形态的能力的特征。或者同一个实现接口,使用不同的实例而执行不同的操作。

  • 如何实现多态?

一般做法是:写一个方法,它只接收父类作为参数,编写的代码只与父类打交道。调用这个方法时,实例化不同的子类对象(new 一个对象)。

更具体地说:

  1. 子类重写父类的方法。使子类具有不同的方法实现。
  2. 把父类类型作为参数类型,该父类及其子类对象作为参数转入,运行时根据实际创建的对象类型动态决定使用那个方法。

# 参考链接

  1. 面向对象的三大基本特征 (opens new window)
  2. 继承与多态的区别 (opens new window)
编辑 (opens new window)
#OOP#封装#继承#多态#面向对象
上次更新: 2024-07-15, 08:03:22
SQLAlchemy 源码阅读
关于 python 中的 setup.py

← SQLAlchemy 源码阅读 关于 python 中的 setup.py→

最近更新
01
提升沟通亲和力的实用策略
03-26
02
工作
07-15
03
如何选房子
06-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 IMOYAO | 别院牧志
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式