目标:
掌握python中的抽象类和抽象接口。
封装和继承在java中用得挺多的,python中貌似用得真不多,但是为了应付考试,也是得了解。
学习内容:
抽象类,就是总结一些基本方法,每个子类必须自己实现这些方法。如果是接口,应该强制子类实现。不实现就报错。
python抽象类和接口的区别:接口中的方法全部需要用抽象方法,强制继承的对象实现。抽象类可以有部分方法已经实现
python 原生不支持接口类,需要导入abc包。python3.4以后自带此包,不用在pip install。
1、 定义一个抽象类。
from abc import abstractclassmethod,ABCMeta
class Car(metaclass=ABCMeta):
@abstractclassmethod
def price(self,money):
pass
@abstractclassmethod
def carryPassengers(self):
pass
class BaomaCar(Car):
def price(self,money =300000):
print('bao ma car is ' + money)
baomaCar = BaomaCar()
baomaCar.price()
运行会报错:说必须实现抽象类中的方法carryPassengers
TypeError: Can't instantiate abstract class BaomaCar with abstract methods carryPassengers
然后修改代码:
from abc import abstractclassmethod,ABCMeta
class Car(metaclass=ABCMeta):
@abstractclassmethod
def price(self,money):
pass
@abstractclassmethod
def carryPassengers(self):
pass
class BaomaCar(Car):
def price(self,money=30000):
print('bao ma car is ' , money)
def carryPassengers(self):
print('bao ma car carry 5 passengers' )
baomaCar = BaomaCar()
baomaCar.price(350000)
baomaCar.carryPassengers()
可以正常运行。
bao ma car is 350000
bao ma car carry 5 passengers
2、 子类可以实现不一样的方法吗?
接着实现一个bus的Car对象。
class Bus(Car):
def price(self):
print('Bus car is ' , 500000)
def carryPassengers(self):
print('Bus car carry 20 passengers' )
bus = Bus()
bus.price()
bus.carryPassengers()
发现可以正常运行,说明abs中 @abstractclassmethod 只限制函数名,只要改函数名实现了就可以了。
3、 如果要强制子类实现一样参数的函数呢?
这就要导入overrides包,java中很常见。
from overrides import overrides
class Bus(Car):
@overrides
def price(self):
print('Bus car is ' , 500000)
def carryPassengers(self):
print('Bus car carry 20 passengers' )
bus = Bus()
bus.price()
bus.carryPassengers()
运行报错:
TypeError: Bus.price: `money` is not present.
overrides要求子类的方法参数必须和父类一致,而且参数名都要一样(子类可以定义新的,但是父类的必须要有,因为python用参数名来确定给哪个参数传值)。当然可以赋初始值。
from overrides import overrides
class Bus(Car):
@overrides
def price(self,money=600000):
print('Bus car is ' , money)
def carryPassengers(self):
print('Bus car carry 20 passengers' )
bus = Bus()
bus.price()
bus.carryPassengers()
运行结果:
Bus car is 600000
Bus car carry 20 passengers
4、 发现python对用了java格式的重载有点不支持。
代码如下:
from abc import abstractclassmethod,ABCMeta
class Car(metaclass=ABCMeta):
@abstractclassmethod
def price(self,money):
pass
from overrides import overrides
class Bus(Car):
@overrides
def price(self,money):
print('Bus car is ' , money)
def price(self,money,tax): #重载price方法
print('Bus car is ' , money + tax)
bus = Bus()
bus.price(money=50) #为啥不去找第一个price(self,money)函数?
运行直接报错:
TypeError: price() missing 1 required positional argument: 'tax'
后来发现:Python是动态类型语言,不支持java形式的重载。如果要重载,就用默认参数代替。为程序员着想的Python!
解决重载的方式,用默认值。
from abc import abstractclassmethod,ABCMeta
class Car(metaclass=ABCMeta):
@abstractclassmethod
def price(self,money):
pass
from overrides import overrides
class Bus(Car):
@overrides
def price(self,money,tax = 10): #重载price方法
print('Bus car is ' , money + tax)
bus = Bus()
bus.price(money=50)
bus.price(money=50,tax=30)
overrides只要包含了父类的参数名money就不会报错。
Bus car is 60
Bus car is 80
学习时间:
半小时足够了
学习产出:
掌握
1、 java的抽象类实现方式,abc模块。抽象类和接口定义。
2、java式的overrides,记得子类必须包含父类的相同参数名
3、 python的重载方式,给参数赋默认值。