如何表达基类方法调用派生虚拟?

时间:2009-12-15 12:43:30

标签: python oop

在C ++中用python执行以下操作的方法是什么?

B* b = new D();
b->virtual_fn();

哪个会在D中调用virtual_fn。是否有一种形式的引用来执行此操作?

2 个答案:

答案 0 :(得分:2)

实际上,Python中的所有实例方法都是虚拟的,并且推断了类型。例如,这有效:

class Vehicle:
  def __init__(self, lp):
    self.license_plate = lp
  def alert(self):
    raise NotImplementedError("Must implement this!")

class Boat(Vehicle):
  def alert(self):
    print "honk, honk!"

class Car(Vehicle):
  def alert(self):
    print "meep meep!"

class FireEngine(Vehicle):
  def alert(self):
    print "woo woo!"

vehicles = [Boat('!'), Car('ADJ-4891'), FireEngine('FRM-1498')]

for v in vehicles:
    print v.license_plate + ': ' + v.alert()

# prints:
# !: honk, honk!
# ADJ-4891: meep meep!
# FRM-1498: woo woo!

答案 1 :(得分:2)

在Python中,值的类型不是变量。后者只是它们当前绑定的值的有用名称。由于变量没有类型,如果您创建一个D对象并将变量绑定到它,那么您将获得D类和B类中任何一个明确定义的方法。没有被替换。实际上,一切都是虚拟的。

现在,如果您要调用已在B中替换的D中的方法,则必须调用该方法并明确传递self。以下是id()为保护无辜者而进行篡改的示例。

>>> class B(object):
...     def virtual_fn(self):
...         print 'in B.virtual_fn() for', id(self)
...     def other_virtual_fn(self):
...         print 'in B.other_virtual_fn() for', id(self)
...     def call_virtual(self):
...         print 'in B.call_virtual() for', id(self)
... 
>>> class D(B):
...     def virtual_fn(self):
...         print 'in D.virtual_fn() for', id(self)
... 
>>> b_obj = B()
>>> d_obj = D()
>>> id(b_obj)
1
>>> id(d_obj)
2
>>>
>>> b_obj.virtual_fn()
in B.virtual_fn() for 1
>>> d_obj.virtual_fn()
in D.virtual_fn() for 2
>>> d_obj.other_virtual_fn()
in B.other_virtual_fn() for 2
>>>
>>> B.virtual_fn(d_obj)
in B.virtual_fn() for 2
>>>
>>> d_obj.call_virtual()
in B.call_virtual() for 2
in D.virtual_fn() for 2
>>>

请记住,d_obj.virtual_fn() D.virtual_fn(d_obj)。因此,如果要显式调用基类的隐藏方法,则不使用 sugar - B.virtual_fn(d_obj)。我强烈建议您阅读Python 2.3中的Method Resolution Order (mro)文档。它真正解释了所有这一切是如何运作的。

修改

在再次阅读问题之后,我添加了call_virtual内容,因为我很确定这是您感兴趣的内容。