面向对象的三大特征(封装、继承、多态)

Python 面向对象的三大特征(封装、继承、多态)解读-LMLPHP

Python是面向对象的语言,支持面向对象编程的三大特性:继承、封装(隐藏)、多态。

封装(隐藏)

继承

多态

1 继承详解

1.1 子类扩展父类

Python 面向对象的三大特征(封装、继承、多态)解读-LMLPHP

继承是面向对象编程的三大特征之一。继承让我们更加容易实现类的扩展。实现代码的重用,不用再重新发明轮子(don’t reinvent wheels)。

如果一个新类继承自一个设计好的类,就直接具备了已有类的特征,就大大降低了工作难度。已有的类,我们称为“父类或者基类”,新的类,我们称为“子类或者派生类”。

Python 面向对象的三大特征(封装、继承、多态)解读-LMLPHP

1.2 语法格式

Python支持多重继承,一个子类可以继承多个父类。继承的语法格式如下:

class 子类类名(父类1[,父类2...]):
    类体

关于构造函数:

  1. 子类不重写 __init__,实例化子类时,会自动调用父类定义的 __init__

  2. 子类重写了**__init__** 时,实例化子类,就不会调用父类已经定义的 __init__

  3. 如果重写了**__init__** 时,要使用父类的构造方法,可以使用 super 关键字,也可以使用如下格式调用:

  4. 父类名.__init__(self, 参数列表)

class Person:
  def __init__(self,name,age):
    print("Person的构造方法")
    self.name = name
    self.age = age
​
  def say_age(self):
    print(self.name,"的年龄是:",self.age)
​
​
class Student(Person):def __init__(self,name,age,score):
    # 子类并不会自动调用父类的__init__(),我们必须显式的调用它。
    # Person.__init__(self, name, age)
    # super(Student,self).__init__(name,age)print("Student的构造方法")
    # self.name = name
    # self.age = age
    self.score = score
​
s1 = Student("张三",15,85)
#s1.say_age()
print(dir(s1))

运行结果:

张三 的年龄是: 15
['_Person__age', '__class__', '__delattr__', '__dict__', '__dir__',
 '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
 '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__'
, '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
 '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__'
, '__subclasshook__', '__weakref__', 'name', 'say_age', 'score']

1.3 成员继承和方法的重写

  1. 成员继承:子类继承了父类除构造方法之外的所有成员。

  2. 方法重写:子类可以重新定义父类中的方法,这样就会覆盖父类的方法,也称为“重写”

【操作】继承和重写的案例

class Person:
  def __init__(self,name,age):
    self.name = name
    self.age = age
​
  def say_age(self):
    print(self.name,"的年龄是:",self.age)def say_name(self):
    print("我是",self.name)
​
​
class Student(Person):def __init__(self,name,age,score):
    Person.__init__(self,name,age) 
    self.score = score
​
  def say_score(self):
    print(self.name,"的分数是:",self.score)def say_name(self):   #重写父类的方法
    print("报告老师,我是",self.name)
​
s1 = Student("张三",15,85)
s1.say_score()
s1.say_name()
s1.say_age()

执行结果:

张三 的分数是: 85
报告老师,我是 张三
张三 的年龄是: 15

1.4 重写str方法

  1. object有一个__str__()方法,用于返回一个对于“对象的描述”。内置函数str(对象),调用的就是__str__()
  2. __str__()经常用于print()方法,帮助我们查看对象的信息。__str__()可以重写
class Person:
  def __init__(self,name,age):
    self.name = name
    self.__age = age
​
  def __str__(self):
    '''将对象转化成一个字符串,一般用于print方法'''
    print("重写__str__方法")
    return "名字是:{0},年龄是{1}".format(self.name,self.__age)
​
p = Person("高淇",18)
print(p)
s = str(p)

1.5 多重继承

Python 面向对象的三大特征(封装、继承、多态)解读-LMLPHP

Python支持多重继承,一个子类可以有多个“直接父类”。这样,就具备了“多个父类”的特点。但是由于,这样会被“类的整体层次”搞的异常复杂,尽量避免使用。

class A:
  def aa(self):
    print("aa")class B:
  def bb(self):
    print("bb")class C(B,A):
  def cc(self):
    print("cc")
​
c = C()
c.cc()
c.bb()
c.aa()

类结构为:

Python 面向对象的三大特征(封装、继承、多态)解读-LMLPHP

1.6 super()获得父类的定义

在子类中,如果想要获得父类的方法时,我们可以通过super()来做。

super()代表父类的定义,不是父类对象。

class A:
  def __init__(self):
    print("A的构造方法")def say(self):
    print("A: ",self)
    print("say AAA")class B(A):
  def __init__(self):
    super(B,self).__init__() #调用父类的构造方法
    print("B的构造方法")
  def say(self):
    #A.say(self)   调用父类的say方法
    super().say()  #通过super()调用父类的方法
    print("say BBB")
​
b = B()
b.say()

运行结果:

A: <__main__.B object at 0x007A5690>
say AAA
say BBB

2 多态详解

Python 面向对象的三大特征(封装、继承、多态)解读-LMLPHP

多态(polymorphism)是指同一个方法调用由于对象不同可能会产生不同的行为。

关于多态要注意以下2点:

  1. 多态是方法的多态,属性没有多态。
  2. 多态的存在有2个必要条件:继承、方法重写
#多态class Animal:
  def shout(self):
    print("动物叫了一声")class Dog(Animal):
  def shout(self):
    print("小狗,汪汪汪")class Cat(Animal):def shout(self):
    print("小猫,喵喵喵")def animalShout(a):
  a.shout()  #传入的对象不同,shout方法对应的实际行为也不同。
​
animalShout(Dog())
animalShout(Cat())
02-28 04:35