简体   繁体   中英

How can I express base class method calling derived virtual?

what's the way to do in python the following in C++?

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

Which would call virtual_fn in D. Are there a form of references to do this?

Effectively, all instance methods in Python are virtual and types are inferred. For example, this works:

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!

In Python, values have types not variables. The latter are simply useful names for the values that they are currently bound to. Since variables do not have types, if you create a D object and bind a variable to it, then you get the methods explicitly defined by the D class and any in the B class that have not been replaced. Effectively, everything is virtual.

Now if you want to call a method in B that has been replaced in D , you have to call the method and pass self explicitly. Here's an example with id() doctored to protect the innocent.

>>> 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
>>>

Remember that d_obj.virtual_fn() is essentially syntactical sugar for D.virtual_fn(d_obj) . So if you want to explicitly call a hidden method of a base class, you do so without the sugar - B.virtual_fn(d_obj) . I would highly recommend reading the Method Resolution Order (mro) document from Python 2.3. It really explains how all of this works rather well.

Edit

After reading the question again, I added the call_virtual stuff since I'm pretty sure that this is what you are interested in.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM