2013-07-17 23 views
3

我有一个教师试图在Python中教OOP的任务。我对C++和C#中的OOP非常熟悉,但难以弄清楚我的某些code中发生了什么。它的工作原理和两个类的功能,因为我想,但我不得不添加一些奇怪的代码,它的工作,我不明白为什么。Python多态性

特别引用在行开始的代码64

class Cone(Cylinder): 

    #Constructor 
    def __init__ (self, radius, height):   
     Cylinder.__init__(self, radius, height) 
     self.calcVolume() 


    def calcVolume(self): 
     Cylinder.calcVolume(self) 
     self.__volume = Cylinder.GetVolume(self) * (1.0/3.0) 

所以实施Cone时,我不明白为什么当锥的构造函数调用缸的构造函数中Cylinder.calcVolume()不叫。如果代码被隐式调用,代码对我来说会更有意义,但我不得不明确地调用该方法。一些指导或解释会很棒。

发布后我做了这个改变是否更有意义?

class Cone(Cylinder): 

    #Constructor 
    def __init__ (self, radius, height):   
     Cylinder.__init__(self, radius, height) 
     self.calcVolume() 


    def calcVolume(self): 
     self.__volume = self.GetBase().GetArea() * self.GetHeight() * (1.0/3.0) 

回答

2

这是当你调用会发生什么Cone.__init__()

  • 它执行Cylinder.__init__()
  • 轮流它调用self.calcVolume()
  • 因为继承的,分辨率顺序认定在Cone类型的方法中,
  • 它调用Cone.calcVolume()代替Cylinder.calcVolume()

__init__()我想你想打电话:

  • Cone.calcVolume(self)Cone.__init__(),或
  • Cylinder.__init__()
  • Cylinder.calcVolume(self)

当然,如果你使用新式类(从object继承),那么你可以只使用type(self).calcVolume(self);然而type(self)在旧式课程上会给你instance类型而不是实际的类,这在你的情况下不起作用。


完整的例子:

class Circle(): 
    #Constructor 
    def __init__ (self, radius): 
     self.__radius = radius 
     self.calcArea() 
    def calcArea(self, PI = 3.14): 
     self.__area = (self.__radius**2) * PI 
    #Get Functions 
    def GetArea(self): 
     return self.__area 
    def GetRadius(self): 
     return self.__radius 
    #Set Functions 
    def SetRadius(self, radius): 
     self.__radius = radius 
     self.calcArea() 

class Cylinder(): 
    #Constructor 
    def __init__(self, radius, height): 
     self.__height = height 
     self.__base = Circle(radius) 
     Cylinder.calcVolume(self) 
    def calcVolume(self): 
     self.__volume = self.__base.GetArea() * self.__height 
    #Get Functions 
    def GetVolume(self): 
     return self.__volume 
    def GetBase(self): 
     return self.__base 
    def GetRadius(self): 
     return self.__base.GetRadius() 
    def GetHeight(self): 
     return self.__height 
    #Set Functions 
    def SetRadius(self, radius): 
     self.__base.SetRadius(radius) 
     self.calcVolume() 
    def SetHeight(self, height): 
     self.__height = height 
     self.calcVolume() 


class Cone(Cylinder): 
    #Constructor 
    def __init__ (self, radius, height): 
     Cylinder.__init__(self, radius, height) 
     Cone.calcVolume(self) 
    def calcVolume(self): 
     Cylinder.calcVolume(self) 
     self.__volume = Cylinder.GetVolume(self) * (1.0/3.0) 
    #Get Functions 
    def GetVolume(self): 
     return self.__volume 
    #Set Functions 
    def SetRadius(self, radius): 
     Cylinder.SetRadius(self, radius) 
     self.calcVolume() 
    def SetHeight(self, height): 
     Cylinder.SetHeight(self, height) 
     self.calcVolume() 


def main(): 
     cylinder = Cylinder(5, 6) 
     cone = Cone(5, 6) 
     circle = Circle(5) 
     print cylinder.GetVolume() 
     print cone.GetVolume() 
     print circle.GetArea() 
     cone.SetHeight(7) 
     print cone.GetVolume() 

main() 
2

规则很简单:当该方法被调用,它的名字是根据方法解析顺序(这是棘手的,因为Python有多重继承)解决。

名称解析后,Python停止搜索(我正在简化)。调用父类的方法(或任何其他方法)由具体的方法决定。隐含地做它可能是问题的常见原因(例如,当您想从父类中重写某些方法时)。

此外,要调用父方法使用super()

Cylinder.__init__(self, radius, height) 

写:

super(Cone, self).__init__(self, radius, height) 

这使得它更加灵活:它只是代表寻找到MRO,然后检查特定的顺序父类适当的方法(在相反的Cone类写本这种情况下,它确实会发现Cylinder.__init__)。

更多阅读:

+0

我返工超()的代码,似乎这是需要新的类中的方法,但是这让我成左右一些Python OOP的东西多一点研究。谢谢 – Thomas