欢迎光临散文网 会员登陆 & 注册

第九章 面向对象-4

2023-07-13 09:39 作者:wangyanhpa  | 我要投稿

9.2继承与多态

面向对象编程的主要优点是面向对象编程符合人类的思维习惯;代码可维护性高,封装可以确保只能使用类允许公开的数据;还有一个重要的是代码复用,代码复用主要通过继承机制实现的。还记得前面我们留下的一个问题吗?

class Person(object):# object这个问题下一节解释(9.2继承与多态)

这里我们多加了一个object,因为Python规定所有的类如果不特殊指定,都继承自object类,所以我们之前定义的类括号里什么都没写,跟这里写了object的是一样的,都是表示类继承自object。通过继承创建的新类称为子类或派生类,被继承的类称为父类、基类或超类。所以Person类是子类,object类是父类,而且object类是所有类的父类。object类定义了多种“魔法”方法,就是名字是__xxxx__()的方法,这类方法具有特殊的功能,如我们学过的__init__方法。除此之外还有__del__,__str__,__new__,__eq__等等。下面通过举例简单介绍一下继承概念。

首先定义一个Shape类,在此基础上派生出Circle类和Triangle类。Shape形状类具有求周长求面积的方法,这个例子需要深入理解。

import math

class Shape():

    def __init__(self,name="shape",color="black",isFilled=True):

        self.name=name

        self.color = color

        self.isFilled = isFilled

        print("Shape __init__")

 

    def __del__(self):

        print("Shape __del__")

 

    def __str__(self):

        return "Shape  name:"+self.name+" color:"+self.color+" isFilled:"+str(self.isFilled)

 

    def getArea(self):

        return 0

 

    def getPerimeter(self):

        return 0

 

class Circle(Shape):

    # Construct a circle object

    def __init__(self, radius=1):

        super().__init__()  #调用父类__init__()方法

        self.radius = radius

        print("Circle __init__")

 

    def __del__(self):     #覆盖父类__del__()方法

        print("Circle __del__")

 

    def __str__(self):     #覆盖父类__str__()方法

        return "Circle  name:" + self.name + " radius:" +str(self.radius) + " color:" + self.color + " isFilled:" + str(self.isFilled)

 

    def getPerimeter(self):

        return 2 * self.radius * math.pi

 

    def getArea(self):

        return self.radius * self.radius * math.pi

 

    def setRadius(self, radius):

        self.radius = radius

 

class Triangle(Shape):

    # Construct a triangle object

    def __init__(self, s1=1, s2=1, s3=1):

        super().__init__()

        self.side1 = s1

        self.side2 = s2

        self.side3 = s3

        print("Circle __init__")

 

    def __del__(self):

        print("Triangle __del__")

 

    def __str__(self):

        return "Triangle  name:" + self.name + " side1:" + str(self.side1) \

               + " side2:" + str(self.side2)+ " side3:" + str(self.side3)+ \

               " color:" + self.color + " isFilled:" + str(self.isFilled)

 

    def getPerimeter(self):

        return self.side1+self.side2+self.side3

 

    def getArea(self):

        #海伦公式

        p=self.getPerimeter()/2

        s=math.sqrt(p*(p-self.side1)*(p-self.side2)*(p-self.side3))

        return s

 

 

def main():

    c=Circle(2)

    print(c)  #显示__str__方法返回值

    print("圆的周长和面积为:",format(c.getPerimeter(),".2f"),format(c.getArea(),".2f"))

 

    t = Triangle(3, 4, 5)

    print(t)  #显示__str__方法返回值

    print("三角形的周长和面积为:",t.getPerimeter(),t.getArea())

    print("the end!")

main()

 

运行结果如下:

Shape __init__

Circle __init__

Circle  name:shape radius:2 color:black isFilled:True

圆的周长和面积为: 12.57 12.57

Shape __init__

Circle __init__

Triangle  name:shape side1:3 side2:4 side3:5 color:black isFilled:True

三角形的周长和面积为: 12 6.0

the end!

Circle __del__

Triangle __del__

 

下面我们看一下多态,类的多态特性要满足以下 2 个前提条件:

继承:多态一定是发生在子类和父类之间;

重写:子类重写了父类的方法。

上面我们在子类中写了__init__,__del__和__str__,子类对象调用时,只调用了自己的方法,父类的同名方法被覆盖。再看下面的例子加深一下理解。

def say(someone):

        someone.say()

 

class Animal:

    def say(self):

        print("动物怎么叫?")

 

class Cat():

    def say(self):

        print("喵喵喵...喵喵喵...")

 

class Dog():

    def say(self):

        print("汪汪汪...汪汪汪...")

 

class Sheep():

    def say(self):

        print("咩咩咩...咩咩咩...")

 

say(Animal())

say(Cat())

say(Dog())

say(Sheep())

 

运行结果如下:

动物怎么叫?

喵喵喵...喵喵喵...

汪汪汪...汪汪汪...

咩咩咩...咩咩咩...

 

此程序中,通过给函数say()添加一个 someone参数,其内部利用传入的 someone调用 say() 方法。这意味着,当调用say() 函数时,我们传给 someone参数的是哪个类的实例对象,它就会调用那个类中的 say() 方法。

下面再看一个继承和多态的综合例子,最后一个例子了!

class Person(object):

    def __init__(self, name, gender):

        self.name = name

        self.gender = gender

 

    def whoAmI(self):

        return 'I am a Person, my name is %s' % self.name

 

class Student(Person):

    def __init__(self, name, gender, score):

        super(Student, self).__init__(name, gender)

        self.score = score

 

    def whoAmI(self):

        return 'I am a Student, my name is %s' % self.name

 

class Teacher(Person):

    def __init__(self, name, gender, course):

        super().__init__(name, gender)

        self.course = course

 

    def whoAmI(self):

        return 'I am a Teacher, my name is %s' % self.name

 

'''

在一个函数中,如果我们接收一个变量 x,则无论该 x 是 Person、Student还是 Teacher,都可以正确打印出结果:

'''

 

def who_am_i(x):

    print(x.whoAmI())

 

p = Person('Dan Gutman', 'Male')

s = Student('A.J.', 'Male', 68)

t = Teacher('Daisy', 'Female', 'English')

 

who_am_i(p)

who_am_i(s)

who_am_i(t)

 

运行结果如下:

I am a Person, my name is Dan Gutman

I am a Student, my name is A.J.

I am a Teacher, my name is Daisy


第九章 面向对象-4的评论 (共 条)

分享到微博请遵守国家法律