点击跳转
《Python入门系列目录》
- 封装、继承、多态
1. 封装
- 在面向对象的编程语言中“封装”就是将抽象得到的属性和行为相结合,形成一个有机的整体(即类)
- 像电视遥控、支付宝支付……,只在意结果,而不在意如何完成这个过程
- 封装可以简化编程,使用者不必了解具体的实现细节
- 封装带来的另一个好处是增强安全性
- 封装也提供了良好的可扩展性,修改盒子内的东西,不会修改到盒子外的东西,增加功能只用在盒子内进行增加,类的使用者不需要改变自己的代码
2. 继承
- 被继承的类称为父类,继承者称为子类
- 子类是父类的特殊化,子类继承了父类的特性,同时可以对继承到的特性进行更改,也可以拥有父类没有的特性
- 若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法,这称之为方法重写
class Animal:
def run(self):
print("run为父类的方法")
class Dog(Animal): # 括号中放父类类名
def run(self):
print("run为子类的方法")
def eat(self):
print("子类特有的方法")
class Cat(Animal): # 括号中放父类类名
pass
# 继承测试
cat = Cat()
cat.run() # run为父类的方法
dog = Dog()
dog.run() # run为子类的方法
dog.eat() # 子类特有的方法
import random as r
class Animal:
def __init__(self):
self.x=r.randint(0,10)
self.y=r.randint(0,10)
def run(self):
self.x+=1
print("我的位置是:",self.x,self.y)
class Cat(Animal):
pass
class Dog(Animal):
def __init__(self):
self.hungry=True
def eat(self):
if self.hungry:
print("我正在吃东西")
self.hungry=False
else:
print("我不想吃东西")
# 继承测试
cat = Cat()
cat.run()
cat.run()
dog = Dog()
dog.eat()
dog.run() # 错误:Dog对象没有x属性
- 解决方法
- 使用super()并不需要传递参数,而用父类类名的方法需要在调用的函数中传入self参数。这是因为,super在调用的时候已经知道调用的对象是什么了,因此不需要再将self传入
class Dog(Animal):
def __init__(self):
Animal.__init__(self) # 缺点:当父类名称发生变化时,这里得修改名称
self.hungry = True
class Dog(Animal):
def __init__(self): # 如果想传入其他参数,需要增加变量
super().__init__() # 如果想传入其他参数,需要增加变量
self.hungry = True
-
继承特点
- 基类初始化__init__不会被自动调用。如果希望子类调用基类的此方法,需要在子类的此方法中显式调用它
- 在调用基类方法时,需要加上基类的类名前缀,且带上self参数变量,或者引入super()机制调用父类中的方法
- Python总是首先查找对应类的方法,如果在子类没有对应的方法,才会在继承链的基类中按顺序查找
- 子类不能访问基类的私有成员
-
继承分类
-
单继承
-
多继承(多个父类)
class 子类名(父类名1, 父类名2, ...)
-
3. 多态
- 在类的继承和类的方法调用时得以体现,根据类型不同表现出不同的行为,无需检查具体类型,只需要知道具体方法即可
# count函数的多态
from random import choice
x = choice(["Hello world!", ["o", "a", 1, 2]])
print(x.count("o")) # 如果x没有count方法,那么会报错,1
- Python和其他静态形态检查类的语言(如C++等)不同,在参数传递时不管参数是什么类型,都会按照原有的代码顺序执行,这就很可能会出现因传递的参数类型错误而导致程序崩溃的现象
- 因此需要程序员自己检查类型