当前位置: 首页 > article >正文

面向对象的三大特性:封装、继承、多态

面向对象编程简单理解就是:基于模板(类)去创建实体(对象),使用对象完成功能开发。

面向对象包含 3 大主要特性:封装、继承、多态。下面,我们将逐一介绍。

一、封装

封装:将现实世界事物的属性和行为封装到类中,描述为成员变量和成员方法,从而完成程序对现实世界事物的描述。

现实世界中事物的部分属性和行为是不能开放给用户使用的,例如在使用手机时,剩余电量,打电话,拍照等属性和行为对用户开放,而驱动信息,程序调度等属性和行为,对用户而言是隐藏的。

作为现实事物在程序中映射的类,提供了私有成员的形式来支持现实事物有不公开的属性和行为。

定义私有成员的方式:

  • 私有成员变量:变量名以 __ 开头( 2 个下划线)
  • 私有成员方法:方法名以 __ 开头( 2 个下划线)

注意:私有成员无法被类对象使用(私有变量无法赋值,私有方法无法被调用,强行调用会报错),但是可以被类中其它的成员使用,如下图所示:

代码示例:

#设计类
class Phone:
    IMEI=None      #序列号
    producer=None  #厂商

    __current_voltage=5 #当前电压

    def call_by_5G(self):
        if self.__current_voltage>=1: #私有成员变量被其他成员使用
            self.__keep_single_core() #私有成员方法被其他成员使用
            print('5G通话已开启')
        else:
            print('通话失败,电量不足')

    def __keep_single_core(self):
        print('让CPU以单核模式运行节省电量')
#创建对象
phone=Phone()
phone.call_by_5G()

输出:

让CPU以单核模式运行节省电量
5G通话已开启

二、继承

软件更新时,软件包里类的部分,每次更新是重新写这个类,还是在原有基础是增删改动呢?答案显而易见,每次更新都要重写这个类,效率太低了,程序员肯定是在原有基础上进行改动,这就涉及到了类的继承。

继承表示从父类那里继承(复制)来成员变量和成员方法(不含私有),被继承的称为父类,主动继承的称为子类,从父类中继承过来的成员变量和成员方法仍然可以正常使用,继承分为:单继承和多继承。

  • 单继承:一个类继承另一个类
  • 多继承:一个类继承多个类

2.1单继承

语法:

class 类名称(父类名称):

    类的属性

    类的行为

代码示例:

#父类
class Phone:
    IMEI=None      #序列号
    producer=None  #厂商
    def call_by_4g(self):
        print('4g通话')
#子类
class Phone2022(Phone): #继承父类
    face_id=True  #面部识别
    def call_by_5g(self):
        print('5g通话')
#创建对象
phone=Phone2022()
phone.IMEI=4398799192  
print(phone.IMEI)  
print(phone.face_id)
phone.call_by_4g()
phone.call_by_5g()

输出:

4398799192
True
4g通话
5g通话

在代码中可以看出,父类中的成员变量IMEI和成员方法call_by_4g在子类对象phone中仍然能正常使用。

2.2多继承

语法:

class 类名称(父类1名称,父类2名称,……,父类n名称):

    类的属性

    类的行为

多继承的多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级,即:先继承的保留,后继承的被覆盖。

代码示例:

class NFCReader:
    nfc_type='第五代'
    producer ='HM'
    def read_card(self):
        print('读取NFC卡')
    def write_card(self):
        print('写入NFC卡')
class RomoteControl:
    rc_type='红外遥控'
    def control(self):
        print('红外遥控开启')
class Phone:
    IMEI=None      #序列号
    producer=None  #厂商
    def call_by_4g(self):
        print('4g通话')

class Phone2022(Phone,NFCReader,RomoteControl): #继承多个父类,用逗号隔开
    face_id=True  #面部识别
    def call_by_5g(self):
        print('5g通话')
#创建对象
phone=Phone2022()
print(phone.producer)
phone.read_card()
phone.control()

输出:

None
读取NFC卡
红外遥控开启

第一个类NFCReader中成员变量producer ='HM',第三个类Phone中成员变量producer=None,这两个类中都有名为producer的成员变量,并且Phone2022将这两个类都继承了,打印输出phone.producer,输出“None”,因为Phone2022在继承多个父类的时候,父类Phone在左,父类NFCReader在右,原则是先继承的保留,后继承的被覆盖。

2.3复写

子类继承父类的成员属性和成员方法后,如果对其“不满意”,可以进行复写,即:在子类中重新定义同名的属性或方法即可

代码示例:

class Phone:
    IMEI=None      #序列号
    producer=None  #厂商
    def call_by_4g(self):
        print('4g通话')

class Phone2022(Phone):
    IMEI=23552321232
    producer='H'
    face_id=True  #面部识别
    def call_by_5g(self):
        print('5g通话')
        print(self.IMEI)
        print(self.producer)
#创建对象
phone=Phone2022()
phone.call_by_5g()

输出:

5g通话
23552321232
H

一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员。如果需要使用(被复写过的)原父类成员,则需要特殊的调用方式 ,有2种方式:

方式一  调用父类成员:

使用成员变量:父类名 . 成员变量
使用成员方法:父类名 . 成员方法 (self)

方式二  使用 super() 调用父类成员:

使用成员变量: super(). 成员变量
使用成员方法: super(). 成员方法 ()

代码示例:

class Phone:
    IMEI=4349854994      #序列号
    producer='M'  #厂商
    def call_by_4g(self):
        print('4g通话')

class Phone2022(Phone):
    IMEI=23552321232
    producer='H'
    face_id=True  #面部识别
    def call_by_5g(self):
        print('5g通话')
        # 方式一调用父类成员
        print(f'序列号为{Phone.IMEI}')
        # 方式二调用父类成员
        print(f'厂商为{super().producer}')
#创建对象
phone=Phone2022()
phone.call_by_5g()

输出:

5g通话
序列号为4349854994
厂商为M

注意:只可以在子类内部调用(被复写过的)原父类成员,子类的实体类对象调用默认是调用子类复写的。

三、多态

多态:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。

同样的行为(函数),传入不同的对象,得到不同的状态,如下列代码所示:

class Animal:
    def speak(self):
        pass  #pass 是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思
class Dog(Animal):
    def speak(self):
        print('汪汪汪')
class Cat(Animal):
    def speak(self):
        print('喵喵喵')

def make_noise(animal:Animal):
    animal.speak()

dog=Dog()
cat=Cat()

make_noise(dog)
make_noise(cat)

输出:

汪汪汪
喵喵喵

父类 Animal 的 speak 方法,是空实现,这种设计的含义是:

  • 父类用来确定有哪些方法
  • 具体的方法实现,由子类自行决定

这种写法,就叫做抽象类(也可以称之为接口)

  • 抽象类:含有抽象方法的类称之为抽象类
  • 抽象方法:方法体是空实现的( pass )称之为抽象方法

抽象类多用于做顶层设计(设计标准),以便子类做具体实现,也是对子类的一种软性约束,要求子类必须复写(实现)父类的一些方法
并配合多态使用,获得不同的工作状态。


http://www.kler.cn/news/321629.html

相关文章:

  • AI/LLM 大模型入门指南
  • 探索EasyCVR视频融合平台:在视频编解码与转码领域的灵活性优势
  • 2024!再见前端!
  • TypeScript 设计模式之【备忘录模式】
  • 搜索插入位置
  • R包compareGroups详细用法
  • MySQL_插入、更新和删除数据
  • Android中大量使用建造者模式(Builder Pattern)的原因可以归结为以下几点:
  • VMware虚拟机Centos操作系统——配置docker,运行本地打包的镜像,进入conda环境(vmware,docker新手小白)
  • MySQL数据查询(基础)
  • 新React v19特性
  • 面试速通宝典——4
  • Java中的注解处理器:自定义注解与APT工具的应用场景
  • 基于SSM+小程序的医院核酸检测服务管理系统(医院2)(源码+sql脚本+视频导入教程+文档)
  • LabVIEW提高开发效率技巧----利用第三方库和工具
  • Spring Boot与Spring Integration:集成模式的现代化实现
  • C++冷门知识点1
  • 基于SpringBoot+Vue+MySQL的电影院购票管理系统
  • word2vector训练数据集整理(代码实现)
  • 设计模式、系统设计 record part01
  • 生信初学者教程(十一):数据校正
  • 【C语言】手把手带你拿捏指针(完)(指针笔试、面试题解析)
  • 算法学习021 c++有多少张桌子 并查集算法学习 中小学算法思维学习 比赛算法题解 信奥算法解析
  • pandas习题 042:将列标签中的日期由近到远排列
  • map的使用
  • FFmpeg源码:avio_skip函数分析
  • 云计算Openstack Nova
  • elasticSearch常见命令及历史数据迁移
  • openlayers中一些问题的解决方案
  • JVM 类加载机制2