基本上继承就类似遗传的概念,比如父母生下子女,如果没有异常情况,那么子女一定会遗传父母的某些特征。当面向对象技术以这种生活实例定义其功能时,就称为继承。

继承是面向对象程序设计的核心概念之一,可以根据现有的类通过继承的机制派生出新类,这种程序代码重复使用的概念可以省去重复编写相同程序代码的大量时间。

如果从程序设计语言的观点来解释,继承就是一种“承接基类的变量和方法”的概念,更严谨的意义则是:“类之间具有层级关系,基类(Derived Class)就是创建好的通用类,而从基类继承而来的派生类(Derived Class)接收了基类的类成员,并在派生类的基础上发展出不桶的类成员”

继承除了可重复使用已开发的类之外,另一项好处在于维持对象封装的特性。这是因为继承时不容易改变已经设计好的类,于是降低了类设计发生错误的机会。

在Python中,已经创建好的类被称为”基类”(Base Class),而经由继承所产生的新类被称为”派生类”(Derived Class)。通常会将基类称为父类或超类,而派生类称为子类。类之间如果有继承的关系,就必须先创建好基类。

继承的优点

  • 提高代码的重复使用性
  • 程序设计人员可以继承标准函数库及第三方函数库

如何定义父类和子类

原则上,父类定义较广义的功能,而子类则定义较侠义的功能,例如父类Biology泛指生物,而其子类Animal、Plant分别指动物与植物。这是因为无论是动物还是植物,都属于生物的一种。所以子类均继承了父类的非私有属性或方法。在子类中,除了继承这些成员外,还可以加入新的成员或覆盖继承自父类的方法。

1.单一继承与多重继承

单一继承(Single Inheritance)是指派生类只继承单独一个基类,在Python中,使用继承机制定义子类的语法如下:

class ChildClass(ParentClass):
    程序语句

# 或
class ChildClass(ParentClass1,ParentClass2,...):
    程序语句

第一种语法子类只继承单一父类,这是单一继承的语法格式;第二种语法子类继承多个父类,这是多种继承的语法格式。

下面先看一下单一继承的实例

class Vehicle: # 基类
    def move(self):
        print('我是可以移动的交通工具')

class Bike(Vehicle): #派生类
    pass

# 创建子类的实例
giand = Bike()
giand.move()

# 返回
我是可以移动的交通工具

其实子类还可以扩展父类的方法而不是完全取代它,我们可以将上面的实例修改如下:

class Vehicle: # 基类
    def move(self):
        print('我是可以移动的交通工具')

class Bike(Vehicle): #派生类
    def move(self):
        Vehicle.move(self)
        print('但是我必须已脚踏方式来移动')

# 创建子类的实例
giand = Bike()
giand.move()
# 返回
我是可以移动的交通工具
但是我必须已脚踏方式来移动

在子类中扩展父类的方法

class Vehicle:
    def move(self):
        print('我是可以移动的交通工具')
class Bike(Vehicle):
    def move(self):
        Vehicle.move(self)
        print('但是我必须已脚踏方式来移动')
class Child_Bike(Bike):
    def move(self):
        Bike.move(self)
        print('为了小朋友的安全,我特别加上辅助轮')

small_giand = Child_Bike()
small_giand.move()

# 返回
我是可以移动的交通工具
但是我必须已脚踏方式来移动
为了小朋友的安全,我特别加上辅助轮

不仅如此,一个子类可以同时继承多个父类

class Animal:
    def feature1(self):
        print('动物是多细胞真核生命体中的一大类群')
class Human:
    def feature2(self):
        print('人类是一种具有情感的高等生物')
class Boy(Animal,Human):
    pass

Andy = Boy()
Andy.feature1()
Andy.feature2()
# 返回

动物是多细胞真核生命体中的一大类群
人类是一种具有情感的高等生物

2.覆盖

覆盖(Override)是重新定义从父类中继承而来的方法,虽然可以在子类中重新改写从父类继承过来的方法,但并不会影响父类中对应的这个方法

class Discount():
    def rate(self,total):
        self.price = total
        if self.price >= 20000:
            print('平时假日的折扣为9折:',end =' ')
            return total*0.9
class Festival(Discount):
    def rate(self,total): # 覆盖rate方法
        self.price = total
        if self.price >= 50000:
            print('国庆节优惠的折扣为5折:', end =' ')
            return total*0.5

Jane = Discount() # 创建父类对象
print(Jane.rate(78000))

Oct = Festival() # 创建子类对象
print(Oct.rate(78000))

# 返回
平时假日的折扣为9折: 70200.0
国庆节优惠的折扣为5折: 39000.0

3.继承相关的函数

在Python中与继承相关的函数有isinstance()和issubclass()。

3.1 isinstance()

isinstance()是Python中的一个内建函数,其语法如下:

ininstance(object,classinfo)

这个内建函数的功能是:如果参数object是参数classinfo类的对象(或实例),或者参数object是参数classinfo类的子类的一个对象就返回True,否则返回False,例如:

>>> num = 8 
>>> isinstance (num,int)
True
>>> isinstance(num,str)
False

3.2 issubclass()

issubclass()同样是Python中的一个内建函数,其语法如下:

issubclass(object,classmethod)

这个内建函数的功能是:如果参数object是参数classmethod类的子类,就返回True,否则返回False

class Parents:
    def hello(self):
        pass
class Child(Parents):
    pass

print( issubclass(Child,object))
print( issubclass(Child,Parents))
# 返回
True
True

4.多态

在程序中,常常会在基类或派生类中声明相同名称但不能功能的Public成员函数。这时可以把函数称为同名异式或多态。例如我们已经创建了某个基类成员的函数open(),并创建了多个由基类派生出来的成员函数open()。当程序开始执行时,可根据打算打开物品的编号来指定要使用哪个派生类的open()成员函数来打开该物品。多态是面向对象语言的一个主要特性。简单来说,Python多态可以让子类的对象以父类来处理。如何实现多态呢?

# 定义多态

# 父类
class Product:
    def __init__(self,name,price):
        self.name = name
        self.price = price
    def profit(self):
        return self.price
    def show(self):
        return self.name
# 子类
class Book(Product):
    def profit(self):
        return self.price * 1.2
# 子类
class Software(Product):
    def profit(self):
        return self.price * 1.5

obj1 = Product('一般商品',2000)
print(f"{obj1.show()}:利润{obj1.profit()}")

obj2 = Book('百科全书',4800)
print(f"{obj2.show()}:利润{obj2.profit()}")

obj3 = Software('计算机软件',12000)
print(f"{obj3.show()}:利润{obj3.profit()}")

# 返回
一般商品:利润2000
百科全书:利润5760.0
计算机软件:利润18000.0

5.合成

合成(Composition,或称为组合)在继承机制中是has_a的关系,例如公司这个类是由会议日期、会议成员和开会地点组合而成的。下面利用这个改变配合Python的程序代码示范如何编写一个合成的程序

# 合成的简易做法
from datetime import date

# 定义Employee公司员工类
class Employee:
    def __init__(self, *title):
        self.title = title

# 定义Metting会议类
class Metting:
    def __init__(self, topic, tday):
        self.topic = topic
        self.tday = tday
        print('开会日期:', self.tday)
        print('开会地点:', self.topic)

# 定义Company公司类,公司类是由员工类和会议类组合而成的
class Company:
    def __init__(self, Employee, Metting):
        self.Emplovee = Employee
        self.Metting = Metting

    def show(self):
        print('参会人员:', self.Emplovee.title)


tday = date.today()  # 获取今天的日期
# Employee对象
member = Employee('研发部主管', '设计部主管', '产品部主管')
place = Metting('会议室', tday)
obj = Company(member, place)
obj.show()

5.练习

实现一个程序,该程序具有选择和删除武功的功能,要求面向对象的方式来实现乔峰的武功,最后列出乔峰的名字及所选武功清单。

class RareBook:
    def __init__(self, name):
        self.__name = name
        self.__books = []

    def get_name(self):
        return self.__name

    def add_book(self, book):
        self.__books.append(book)

    def drop_book(self, book):
        self.__books.remove(book)

    def get_book(self):
        return self.__books


hero = RareBook('乔峰')
hero.add_book('降龙十八掌')
hero.add_book('打狗棒法')
hero.add_book('鳞波微步')
hero.add_book('龙爪手')
hero.drop_book('鳞波微步')

print(f"{hero.get_name()}的武功有{hero.get_book()}")

# 返回
乔峰的武功有['降龙十八掌', '打狗棒法', '龙爪手']

发表评论

电子邮件地址不会被公开。 必填项已用*标注