# 类的继承

# 类的继承

  • 类的继承,顾名思义,指的是一个类既拥有另一个类的特征,也拥有不同于另一个类的独特特征。在这里的第一个类叫做子类,另一个叫做父类,特征其实就是类的属性和函数。
  • 每个类都有构造函数,继承类在生成对象的时候,是不会自动调用父类的构造函数的,因此你必须在 init() 函数中显式调用父类的构造函数。它们的执行顺序是 子类的构造函数 -> 父类的构造函数。
  • 继承的优势:减少重复的代码,降低系统的熵值(即复杂度)。
  • 可以使用抽象函数装饰器(@abstractmethod)实现特殊功能,类只能当做父类,不能直接实例化,函数必须重写。

class Entity():
    def __init__(self, object_type):
        print('parent class init called')
        self.object_type = object_type
  
    def get_context_length(self):
        raise Exception('get_context_length not implemented')
  
    def print_title(self):
        print(self.title)

class Document(Entity):
    def __init__(self, title, author, context):
        print('Document class init called')
        Entity.__init__(self, 'document')
        self.title = title
        self.author = author
        self.__context = context
  
    def get_context_length(self):
        return len(self.__context)
  
class Video(Entity):
    def __init__(self, title, author, video_length):
        print('Video class init called')
        Entity.__init__(self, 'video')
        self.title = title
        self.author = author
        self.__video_length = video_length
  
    def get_context_length(self):
        return self.__video_length

harry_potter_book = Document('Harry Potter(Book)', 'J. K. Rowling', '... Forever Do not believe any thing is capable of thinking independently ...')
harry_potter_movie = Video('Harry Potter(Movie)', 'J. K. Rowling', 120)

print(harry_potter_book.object_type)
print(harry_potter_movie.object_type)

harry_potter_book.print_title()
harry_potter_movie.print_title()

print(harry_potter_book.get_context_length())
print(harry_potter_movie.get_context_length())

########## 输出 ##########

Document class init called
parent class init called
Video class init called
parent class init called
document
video
Harry Potter(Book)
Harry Potter(Movie)
77
120

# 是否子类:isinstance和type

isinstance 和 type 的区别在于:

  • type()不会认为子类是一种父类类型。
  • isinstance()会认为子类是一种父类类型。
>>> class A:
...     pass
... 
>>> class B(A):
...     pass
... 
>>> isinstance(A(), A)
True
>>> type(A()) == A 
True
>>> isinstance(B(), A)
True
>>> type(B()) == A
False

# 新式类和旧式类

在早期版本的 Python 中,所有类并没有一个共同的祖先 object​,如果定义一个类,但没有显式指定其祖先,那么就被解释为 旧式类,例如:

class oldA:  
	pass

class oldB:
    pass

其中,oldA​ 和 oldB​ 都属于旧式类

Python 2.x​ 版本中,为了向后兼容保留了旧式类。该版本中的 新式类必须 显式继承 object​ 或者其他新式类:

class NewA(object):  
    pass

class NewB(NewA):  
    pass

显然,以上两个类都属于 新式类

而在 Python 3.x​ 版本中,不再保留旧式类的概念。因此,**没有继承任何其他类的类都隐式地继承自 object**​。