【面向对象编程】(4) 类的继承,重构父类中的方法

各位同学好,今天和大家分享一下面向对象编程中,类的三大特征之继承。主要介绍:子类继承父类的基本方法;重写父类的类方法;重构父类的初始化方法;super() 方法本节主要是单继承多继承在下一节中介绍。如果对基础知识不太清楚的,可以看一下我的前几篇博客:https://blog.csdn.net/dgvv4/category_11569694.html?spm=1001.2014.3001.5482

继承是使子类具有父类的各种属性和方法,不需要编写相同代码。在子类继承父类的同时,可以重新定义父类中的某些属性,并重写某些方法,即覆盖父类的原有属性和方法,使其获得与父类不同的功能。


1. 子类继承父类的基本方法

首先定义父类 Animal父类中定义的属性和方法都可以被子类调用。定义子类时,在子类名后面加括号,括号内填入父类的名称,即可完成对父类的继承。子类继承父类  class 子类名(父类名):

子类 Pig 在实例化时,直接调用父类的初始化方法,因此子类在初始化时输入的属性与父类相同子类的实例 pig 可直接调用父类方法pig.eat(),父类中eat()方法中的第一个参数 self 是子类的实例化对象pig

子类 Bird 在定义时,设置了该子类特有的方法 fly(),子类 Bird 的实例化对象 bird 既能调用父类的方法eat(),也能调用自身的子类方法fly()

#(1)定义父类
class Animal:  

    life_val = 100  # 定义父类的属性    

    # 父类初始化
    def __init__(self, name:str, age:int, sex:str):
        
        # 分配属性
        self.name = name
        self.age = age
        self.sex = sex
        
    # 定义父类中的方法
    def eat(self):
        
        print(f'{self.name} is eating')
      

#(2)定义子类
# 在类名后面加括号,代表继承,括号里面填写父类的名称    
class Pig(Animal):  # 子类可以调用父类中的属性和方法。
    pass    # 这里子类什么都不写


#(3)定义子类,继承父类属性
class Bird(Animal):  # 子类可以调用父类中的所有属性和方法
    
    # 每个子类有其特有的方法
    def fly(self):
        
        print(f'{self.name} can fly')

   
#(4)对子类实例化,子类继承了父类,传入属性时需要和父类的格式一致
pig = Pig('小花', 5, 'male')
# 调用父类中的方法
pig.eat()  # 小花 is eating
# 通过子类调用父类中的属性
print(pig.life_val)  # 100

#(5)对子类实例化,子类继承了父类的属性和方法
bird = Bird('阿伟', 10, 'female')
# 调用子类自己的方法
bird.fly()  # 阿伟 can fly

2. 子类重写父类的类方法

子类重写父类的类方法有两种。一种是完全重写父类方法,即不执行父类中的某个类方法,只执行子类中重写的某个父类的类方法。另一种是在父类的方法上补充,即先执行父类中的某个类方法,再执行子类中在父类的某个方法基础上新增的几条命令。

子类 Person1 在定义时,完全重写父类方法 eat(),其实例 person1 调用该方法时,直接执行的是子类中的 eat() 方法。而子类 Person2 在定义时,在父类的 eat() 方法上做补充。person2.eat() 先调用父类方法 Animal.eat() 再执行新增加的语句。 

#(1)定义父类
class Animal:  

    life_val = 100  # 定义父类的属性    

    # 初始化
    def __init__(self, name:str, age:int, sex:str):
        
        # 分配属性
        self.name = name
        self.age = age
        self.sex = sex
        
    # 定义父类中的方法
    def eat(self):
        
        print(f'{self.name} is eating')


#(2)定义子类person1
class Person1(Animal):  # 继承父类的属性和方法
    
    # 定义子类自身的方法
    def talk(self):
        print(f'{self.name} can talk')
    
    # 完全重写父类方法,执行时,不执行父类中的该方法
    def eat(self):
        print(f'{self.name} is happily eating')


#(3)定义子类person2
class Person2(Animal): # 继承父类的属性和方法
    
    # 重写父类方法:先执行父类方法,再执行子类方法
    def eat(self):
        
        # 先执行父类的方法
        Animal.eat(self)  # 该self是子类的实例化对象
        # 再执行子类重写后的方法
        print(f'{self.name} is happily eating')


#(4)对子类person1实例化,继承父类属性,改写父类方法
person1 = Person1('阿强', 30, 'male')
# 调用重写后的父类方法
person1.eat()  # 阿强 is happily eating


#(5)对子类Person2实例化
person2 = Person2('阿伟', 10, 'male')
# 调用重写的父类方法
person2.eat()
# 阿伟 is eating
# 阿伟 is happily eating

3. 子类重构父类的初始化方法

3.1 完全重写父类的初始化方法

子类继承父类后如果不在子类中定义初始化方法,那么子类的初始化方法就和父类的初始化方法相同如果子类定义了自己的初始化方法,那么子类实例化时就不会调用父类的初始化方法

子类 Pig 定义了自身的初始化方法 def __init__(self, name:str, height:int, weight:int),那么在子类实例化时 pig = Pig('阿强', 50, 200) ,就和父类的初始化方法无关,完全重写了父类的初始化方法。

#(2)定义父类
class Animal:
    
    life_val = 100  # 父类的类属性 
    
    #(2)初始化
    def __init__(self, name:str, age:int, sex:str):
        
        # 分配属性
        self.name = name
        self.age = age
        self.sex = sex
    
    # 定义父类的类方法
    def eat(self):
        
        print(f'{self.name} is eating')
    
#(3)定义子类,继承父类的所有属性和方法
class Pig(Animal):
    
    #(4)完全重写父类中的初始化方法,不再执行父类中的初始化方法
    def __init__(self, name:str, height:int, weight:int):
        
        # 分配属性
        self.name = name
        self.height = height
        self.weight = weight
    
    # 定义子类的特有方法
    def claim(self):
        print(f"{self.name}'s weight is {self.weight} and height is {self.height}")
        
#(5)实例化子类,这时候只需要传入重写后的初始化的属性
pig = Pig('阿强', 50, 200)
# 调用子类的方法
pig.claim()  # 阿强's weight is 200 and height is 50

3.2 在父类初始化的基础上添加新属性

如果我们只是希望在父类的初始化基础上添加属性,仍需要调用父类中的初始化方法,那我们该怎么做呢。和前面的重构父类的类方法类似。这里我们只需要先调用父类的初始化方法,再添加新的属性

子类 Pig 在定义时,初始化传入的属性在父类属性的基础上增加了 weightheight ,为避免重复写代码,因此,先调用父类初始化方法 Animal.__init__(self, 属性名),其中 self 子类 Pig 的实例化对象属性名子类初始化时传入的属性中和父类初始化相同的属性。然后再添加新属性 self.weight = weight 等即可。

这里也调用了父类的类方法,在子类的 claim() 方法中,先执行父类中的 Animal.eat(),再执行其他的语句。

#(1)定义父类
class Animal:
    
    life_val = 100  # 父类的类属性 
    
    #(2)初始化
    def __init__(self, name:str, age:int, sex:str):
        
        # 分配属性
        self.name = name
        self.age = age
        self.sex = sex
    
    # 定义父类的类方法
    def eat(self):
        
        print(f'{self.name} is eating')

#(3)定义子类
class Pig(Animal):
    
    #(4)在父类初始化属性的基础上,添加属性
    def __init__(self, name:str, age:int, sex:str, weight:int, height:int):
        
        # 调用父类的初始化方法,减少代码量。self为子类的实例对象
        Animal.__init__(self, name, age, sex)
        
        # 添加新的属性
        self.weight = weight
        self.height = height
        
    # 定义子类方法
    def claim(self):
        
        # 先执行父类中的eat()方法
        Animal.eat(self)  # 传入子类的实例化对象
        # 执行完父类中的方法后在执行下面的
        print(f'{self.name} is {self.age} years old, its weight is {self.weight}')


#(5)子类实例化
pig = Pig('阿花', 5, 'male', 200, 50)
# 调用子类方法
pig.claim()
# 阿花 is eating
# 阿花 is 5 years old, its weight is 200

4. super() 方法

super() 方法用于子类继承父类中的方法,和上面类似

子类继承父类的初始化方法

(1)super( 子类名, self ).__init__( 父类属性名 )

(2)super( ).__init__( 父类属性名 )

子类继承父类的类方法

(1)super( 子类名, self ).父类方法名( 除 self 以外的参数 )

(2)super( ).父类方法名( 除 self 以外的参数参数 )

如下面代码中,子类 Pig 在初始化时调用父类初始化方法 super(Pig, self).__init__(name, age, sex) ,其中 Pig 是这个子类的名称,self 是该子类的实例化对象,__init__() 中的参数和父类的初始化属性名相同。也可以省略super()括号中的参数,变成 super().__init__(name, age, sex) ,这两种方法是等价的。

这里的 super() 方法和我们上面介绍的调用父类的方法是通用的,等价于  Animal.__init__(self, name, age, sex) ,这种方法更直观一般用在 python2 里面。

子类 Pig 调用父类中的类方法 super(Pig, self).eat() ,其中 Pig 是子类名称,self 是子类的实例化对象,eat() 是父类中的方法。也可以省略 super() 括号中的参数,变成 super().eat()

也可以使用我们上面用到的 Animal.eat(self) , 同样能调用父类中的类方法

#(1)定义父类
class Animal:
    
    life_val = 100  # 父类的类属性 
    
    # 初始化
    def __init__(self, name:str, age:int, sex:str):
        
        # 分配属性
        self.name = name
        self.age = age
        self.sex = sex
    
    # 定义父类的类方法
    def eat(self):
        
        print(f'{self.name} is eating')

#(2)定义子类调用父类方法
class Pig(Animal):
    
    # 初始化
    def __init__(self, name:str, age:int, sex:str, weight:int, height:int):
        
        #(3)调用父类的初始化方法
        super(Pig, self).__init__(name, age, sex)
        # 同 super().__init__(name, age, sex)
        
        # 在父类基础上添加新的属性
        self.weight = weight
        self.height = height
        
    # 定义子类方法
    def claim(self):
        
        #(4)调用父类中的eat方法
        super(Pig, self).eat()
        # 同 super().eat()
        # 执行完eat方法之后再执行下面的
        print(f"{self.name} is {self.age} years old, its weight is {self.weight}")

#(5)实例化子类
pig = Pig('阿强', 5, 'male', 200, 50)
# 调用子类方法
pig.claim()
# 阿强 is eating
# 阿强 is 5 years old, its weight is 200
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

立Sir

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

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

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

打赏作者

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

抵扣说明:

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

余额充值