【面向对象编程】(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 = nameself.age = ageself.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 = nameself.age = ageself.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 = nameself.age = ageself.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 = nameself.height = heightself.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 在定義時,初始化傳入的屬性在父類屬性的基礎上增加了 weight 和 height ,為避免重復寫代碼,因此,先調用父類初始化方法?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 = nameself.age = ageself.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 = weightself.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 = nameself.age = ageself.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 = weightself.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
總結
以上是生活随笔為你收集整理的【面向对象编程】(4) 类的继承,重构父类中的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【面向对象编程】(3) 类之间的交互,依
- 下一篇: 【神经网络】(10) Resnet18、