day6-类的继承

概述

面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

通过继承创建的新类称为“子类”或“派生类”。

被继承的类称为“基类”、“父类”或“超类”。

继承的过程,就是从一般到特殊的过程。

要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。

在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

继承概念的实现方式主要有2类:实现继承、接口继承。

1.         实现继承是指使用基类的属性和方法而无需额外编码的能力;
2.         接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法);
在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。
 
抽象类仅定义将由子类创建的一般属性和方法。

OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。

类的继承

不带参数的继承

1.继承的定义

用法:在类名的括号中写入需要继承的类名即可

class Person(object):

    def talk(self):
        print("person is talking.....")


class BlackPerson(Person):  #继承Person这个类

      def walk(self):  #定义子类自身的walk方法
          print("black person is blaaa......")

b = BlackPerson()
b.talk()  #由于继承了父类的talk()方法,所以可以被调用
b.walk()  #调用子类自身的walk方法
#输出
person is talking.....
black person is blaaa......

2.子类对父类方法的重写

class Person(object):  #定义person类


    def talk(self):  #定义方法talk
        print("person is talking.....")


class BlackPerson(Person): #继承Person类

      def walk(self): #定义自己的方法
          print("black person is blaaa......")

      def talk(self): #重写父类
          print("black person is talking ... ")

b = BlackPerson()
b.talk()
b.walk()
#输出
black person is talking ... 
black person is blaaa......

解析:如果在子类BlackPerson中重写了父类的方法,那么就调用子类的方法,子类中没有对父类方法进行重写的话,那么就调用父类的方法,这就是继承。

带参数的继承

构造方法的继承

用法:因为子类有自己的属性,但是又想继承父类的属性,所以需要先继承,再重构

继承类的构造方法2种写法:

  1. 经典类写法:父类.__init(self,name,age)
  2. 新式类写法:super(子类,self).__init__(name,age)

注:建议使用新式类的写法,因为使用经典类的写法,在多继承的情况下,会出现重复调用参数的可能

class Person(object):  #定义person类

    def __init__(self,name,age):
        self.name = name
        self.age = age

    def talk(self):  #定义方法talk
        print("person is talking.....")


class BlackPerson(Person): #继承Person类

      def walk(self): #定义自己的方法
          print("black person is blaaa......")

      def talk(self): #重写父类
          print("black person is talking ... ")

b = BlackPerson()
b.talk()
b.walk()
#输出
Traceback (most recent call last):
  File "C:/Users/huwei/PycharmProjects/module_2/类的继承.py", line 19, in <module>
    b = BlackPerson()
TypeError: __init__() missing 2 required positional arguments: 'name' and 'age'

解析:在这儿为什么报错?从报错信息中可以看出,没有参数的传入,为什么报错?因为在BlackPerson里面没写构造函数,那么子类BlackPerson就继承父类的,而父类的构造函数要求必须有参数传入,而这时,子类没有参数传入,因此,出现报错。

接着,我们对调用进行修改
b = BlackPerson("Dick",20)即可。

再者,如果我们想要同时继承父类的方法,且子类又想增加别的构造函数,怎么办?通过一个例子来说说先继承,再重构:

class Person(object):  #定义person类

    def __init__(self,name,age): #形式参数
        self.name = name   #self = b  --->  self.name = b.name
        self.age = age
        self.sex = "normal"   #默认的,不需要传参数进来

    def talk(self):  #定义方法talk
        print("person is talking.....")


class BlackPerson(Person): #继承Person类
      #先继承,再重构↓
      def __init__(self,name,age,strenth):  #1 定义时需要传入父类的属性名
          Person.__init__(self,name,age)  #继承父类的构造方法  #经典类
          #super(BlackPerson,self).__init__(name,age) #新式类(推荐)
          self.strenth = strenth  #定义子类本身的属性
          print(self.name,self.age,self.strenth)
      def walk(self): #定义自己的方法
          print("black person is blaaa......")

      def talk(self): #重写父类
          Person.talk(self)
          print("black person is talking ... ")

class WhitePerson(Person):
    pass

b = BlackPerson("Dick",28,"strong")
#输出
Dick 28 strong
#经典类与新式类,选其一

这里有一个疑问?我们为什么不能在子类中重新写一遍,为什么要继承父类中的方法(构造函数)呢?因为你重新写一遍的话,#1处因为我们只传进来name和age,所以只能继承self.name和self.age,那self.sex怎么办,它也需要重写吗?所以,只有把父类中的构造函数全部继承过来,使用先继承,再重构的方法,下面是调用的流程:

解析:b对象通过BlackPerson实例化后,虽然BlackPerson构造函数继承了父类的,但是我们对其进行了先继承后重构,所以,当我们实例化时对子类本身形参进行了调用,实际上子类本身的形参将其自己传给了父类的构造函数,self = b,所以能够打印出name,age,sex。

类的继承实例

单继承

class SchoolMember(object):
    """学校成员基类"""

    member = 0
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
        self.enroll()


    def enroll(self):
        """注册"""
        print("just enrolled a new school member [%s]" %self.name)
        SchoolMember.member +=1

    def tell(self):
        print("------%s-------"%self.name)
        for k,v in self.__dict__.items():
             print("\t",k,v)

        print("===end===")
    def __del__(self):
        print("开除了[%s]..."%self.name)
        SchoolMember.member -=1


class Teacher(SchoolMember):
    """讲师类"""

    def __init__(self,name,age,sex,salary,course):
        # SchoolMember.__init__(self,name,age,sex)  #经典类写法
        super(Teacher, self).__init__(name,age,sex)  #新式类写法
        self.salary = salary
        self.course = course



    def teaching(self):
        print("Teacher [%s] is teaching [%s]"%(self.name,self.course))


class Student(SchoolMember): #单继承
    def __init__(self,name,age,sex,course,tuition):
        SchoolMember.__init__(self,name,age,sex)
        self.course = course
        self.tuition = tuition
        self.amount = 0

    def paytuition(self,amount):
        print("student [%s] has just paied [%s]"%(self.name,amount))
        self.amount +=amount


t1 = Teacher("Dick",28,"M",3000,"Python")
s1 = Student("Sophie",25,"F","SAP",18000)
s2 = Student("Jacky",25,"M","SAP",15000)

print(SchoolMember.member)
t1.tell()
s2.tell()
del s2

print(SchoolMember.member)

#输出
just enrolled a new school member [Dick]
just enrolled a new school member [Sophie]
just enrolled a new school member [Jacky]
3
------Dick-------
	 salary 3000
	 course Python
	 name Dick
	 age 28
	 sex M
===end===
------Jacky-------
	 course SAP
	 amount 0
	 tuition 15000
	 name Jacky
	 age 25
	 sex M
===end===
开除了[Jacky]...
2
开除了[Dick]...
开除了[Sophie]...
posted @ 2017-08-05 22:22  Mr.hu  阅读(157)  评论(0编辑  收藏  举报