0

I want to use the superclass to call the parent method of a class while using a different class.

Class AI():
...

 for i in self.initial_computer_group:
             if i.rect.x == current_coords[0] and i.rect. y== current_coords[1]:
                 i.move(coords_to_move[0], coords_to_move[1])

i.move() calls a method from an inherited class, when I want the original method from the parent class.

self.initial_computer_group contains a list of objects which are completely unrelated to the AI class.

I know I need to somehow get the class name of the current object i references to, but then I don't know what to use as the second argument in super() as i can't use self, since it's unrelated to AI.

So how do I use super() when I'm in a completely different class to what super is meant to call?

Note: I want to call the parent method as it speeds everything up. I only designed the inherited method to ensure the human isn't breaking the rules in this chess game.

EDIT: I found a solution by changing the name of the inherited method to something else, but I was wondering whether there's still a special way to invoke super() to solve the problem

83457
  • 203
  • 1
  • 11

3 Answers3

3

It sounds like you want to call a specific class's method, no matter what the inheritance graph looks like (and in particular, even if that method happens to be overridden twice). In that case, you don't want super. Instead, call the class's method directly. For example, assuming the version you want is in the Foo class:

Foo.move(i, coords_to_move[0], coords_to_move[1])
user2357112
  • 260,549
  • 28
  • 431
  • 505
  • I didn't override the method twice, unless you mean for the different objects which would be more than twice – 83457 Aug 04 '14 at 13:24
  • @83457: Perhaps you didn't, but it's best not to tie your code to assumptions like "the class I'm interested in is the direct parent of the classes I'm receiving". It makes your code less flexible and tends to introduce weird bugs. – user2357112 Aug 04 '14 at 13:30
  • Fair point, but it's not an assumption. The objects in initial_computer_group must all have the same parent class otherwise the chess game wouldn't work at all. And you're solution works fine, but doesn't it also make the same assumption as your statement? – 83457 Aug 04 '14 at 13:39
  • @83457 In general, if you have a situation where you can't treat any object that inherits from a base class as the base class, then you need to rethink your design because you've just defeated the purpose of polymorphism (as well as the purpose of duck-typing in a dynamic language). If you have a [Fragile Base Class](http://en.wikipedia.org/wiki/Fragile_base_class), then you might want to look into using the [Template Method Pattern](http://en.wikipedia.org/wiki/Template_method_pattern) to help alieve its fragility. – aruisdante Aug 04 '14 at 13:40
  • @83457 Also, you missed the point of user2357112's comment. Tying the assumption about a method being called to the *direct* parent of a class you receive breaks for an inheritance chain more than 1 deep (I.E. grand-child will call child, not parent) or if you receive a parent directly. – aruisdante Aug 04 '14 at 13:45
  • @aruisdante my code above works fine as the base class, but I just didn't want to call the inherited method because it wastes time. Basically, the move method in the inherited class, checks whether the move the human player is trying to make is legal before moving it. The AI class already knows all the legal moves, so invoking the move method of the inherited class is a waste of time, so i want to directly go to the parent method to avoid needless evaluating – 83457 Aug 04 '14 at 13:48
  • 1
    Then why not make either a) A private method that does the basic ``move`` functionality, is called by the public method in the base class, and your AI specific implementation calls that directly, or even better b) make an AI inherited class that only does the processing you want it to do? Generally speaking, ignoring the inheritance chain from outside of said inheritance chain can result in some really hard to track down bugs later on down the line. As this answer demonstrates, what you want to do is certainly possible, but your use-case for doing it seems poor. – aruisdante Aug 04 '14 at 14:12
0

As it's hard to read code in comments, here's a simple example:

class BaseClass():
    def func(self):
        print("Here in BaseClass.")


class InheritedClass(BaseClass):
    def func(self):
        print("Here in InheritedClass.")


def func(instance):
    super(InheritedClass, instance).func()

In use:

>>> func(InheritedClass())
Here in BaseClass.

But this clearly makes your code less flexible (as the instance argument must be an InheritedClass instance), and should generally be avoided.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
0

Given some inheritance hierarchy:

class Super:                 # descends from object 
    def func():
        return 'Super calling'

class Base(Super):
    def func():
        return 'Base calling'

class Sub(Base):
    def func():
        return 'Sub calling'        

You can get the resolution hierarchy with the __mro__ attribute:

>>> s=Sub()
>>> s.__class__.__mro__
(<class '__main__.Sub'>, <class '__main__.Base'>, <class '__main__.Super'>, <class 'object'>)

Then you can pick among those by index:

>>> s.__class__.__mro__[-2]
<class '__main__.Super'>
>>> s.__class__.__mro__[-2].func()
Super calling

You can get a specific name by matching against the __name__ attribute:

def by_name(inst, tgt):
    for i, c in enumerate(inst.__class__.__mro__):
        if c.__name__==tgt:
            return i

    return -1    

Then if you want to call the parent class of an unrelated class, just use one of these methods on an instance of the descendant class with the method of interest.

Of course the simplest answer is if you know the class and method you want, just call it directly:

>>> Super.func()
Super calling
>>> Base.func()  
Base calling  

If you need to go several levels up (or an unknown number of levels up) to find the method, Python will do that for you:

class Super:
    def func():
        return 'Super calling'

class Base(Super):
    pass

class Sub(Base):
    pass    

>>> Sub.func()
Super calling
Community
  • 1
  • 1
dawg
  • 98,345
  • 23
  • 131
  • 206