在Python中,类的继承与函数的重写,是我们再熟悉不过的知识点。但如何实现,方法的强制重写与禁止重写,这大概是很多初学者的一个知识盲区吧?
**需求:**父类一个方法,强制子类去重写。
实现的方法大约有这两种:
1、把父类变为抽象基类,然后给指定方法加上装饰器@abc.abstractmethod
2、指定方法抛出NotImplementedError异常
先来说说第一种
由于定义抽象基类,Py2和Py3有所区别,这里都举个例。
Python2.x中
# coding:utf-8
import abc
class Animal(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def speak(self):
pass
class Dog(Animal):
def speak(self):
print("汪汪...")
class Cat(Animal):
pass
if __name__ == '__main__':
dog = Dog()
dog.speak()
cat = Cat()
cat.speak()
输出结果
汪汪...
Traceback (most recent call last):
File "F:/Python Script/hello.py", line 116, in <module>
cat = Cat()
TypeError: Can't instantiate abstract class Cat with abstract methods speak
如果是Python3.x中,只需把 Animal 类改成如下即可
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod
def speak(self):
pass
输出结果,报错。
Traceback (most recent call last):
汪汪...
File "F:/Python Script/hello.py", line 114, in <module>
cat = Cat()
TypeError: Can't instantiate abstract class Cat with abstract methods speak
以上说明,只要把一个方法定义成抽象方法,那解释器就会要求子类,必须实现(重写)这个方法,否则就会报TypeError异常。
要注意的是,这个异常在实例化时,就会抛出,而不需要等到调用函数。
再来说说,第二种方法
我们给父类的speak方法,加上抛出异常语句。他会帮我们检测,这个方法在子类中有没有被重新实现,没有的话,就会抛出异常。
class Animal():
def speak(self):
raise NotImplemented
class Dog(Animal):
def speak(self):
print("汪汪...")
class Cat(Animal):
pass
if __name__ == '__main__':
dog = Dog()
dog.speak()
cat = Cat()
cat.speak()
运行后,报错,提示我们这个方法没有被重写。
汪汪...
Traceback (most recent call last):
File "F:/Python Script/hello.py", line 114, in <module>
cat.speak()
File "F:/Python Script/hello.py", line 101, in speak
raise NotImplemented
TypeError: exceptions must derive from BaseException
要注意的是,这个异常只有在调用speak函数时,才会抛出。
其实这个说法并不太准确。实际是可以重写的,只是无法生效而已。
来看下这个常规的例子。
class Base:
def go(self):
print("base")
def run(self):
self.go()
class Extend(Base):
def go(self):
print("extend")
person = Extend()
person.run()
输出结果,很正常,和我们的预期符合。
extend
先不要开心太早,来看看下面这个例子
class Base:
def __go(self):
print("base")
def run(self):
self.__go()
class Extend(Base):
def __go(self):
print("extend")
person = Extend()
person.run()
输出如下,你一定很纳闷,为什么会这样。
base
仔细观察一下,其实区别只有,一个是公开函数,一个私有函数。
于此,我们可以得出结论。
私有函数的作用范围仅在当前类,其表象上可以被重写,但实际上并无重写的效果。
如果你想学习自动化测试、性能测试、测试开发,但是自己又非常的迷茫,没有思路又怕耽误时间,那么你可以找我。我非常愿意将自己从业10年的经验传授给你,也愿意将自己独家的核心教程免费赠送。
公众号【程序员阿沐】找到我!我一直在等着你!