1

I'm a newbie in writing OO program, and I cannot find any good solution of the problem I'm facing. May anyone please help?

I'm sourcing some modules which I cannot freely modify it, and I would like to add a method on a superclass so that I can call on instances of subclasses. So in my module:

import externalLib as myLib

class Superclass(myLib.Superclass):

    def myNewMethod(self):
        print(self.name)   # Print a member variable

def __main__():

    obj = myLib.Subclass(args)
    obj.myNewMethod()    # Expect prints the same member variable in subclass

Result: "Subclass" has no attribute or method named "myNewMethod".

  1. Extending all the subclass is not possible to me, as there are too many subclasses.

  2. I could solve the problem by defining the function under my module instead of the Superclass, but I just think that way is not like an OO-architecture.

Is there any better solution? Or any keywords or OO design concept can I refer to?

Thanks!

  • In time, we usually don't use the verb "to source" (as in "I am sourcing") to imply we are importing modules in a Python application. This verb comes from the fact that certain languages, notably PHP actually "paste" the included file source code verbatim in the caller file. Python does this through high level mechanisms that actually instantiate the included modules as Python objects, and they are processed just once per application, even if included multiple times. – jsbueno Jan 13 '14 at 13:12

2 Answers2

2

Yes, there is one keyword - "wrong". OO is model, where what you want to do should NOT be done.

If you have REALLY good reason for that, you can do it much simpler:

import externalLib as myLib

def myNewMethod(self):
    print(self.name)

myLib.Superclass.myNewMethod = myNewMethod

Why didn't your code work?

When you defined Superclass inheriting from myLib.Superclass, it stayed ONLY in this module. When you defined your Superclass, name "Superclass" was bind with your new class only in global scope, but old value didn't change, co Superclass in myLib/externalLib scope stayed the same. I can see how you got impression that it may work, if you worked with classic-OO languages like Java or C++.

Little known fact - Java/C++ OO model is not really object-oriented. It does such impression, but OOP model is REALLY implemented in Smalltalk.

Filip Malczak
  • 3,124
  • 24
  • 44
  • Thanks! It works. By the way, what kind of implementation would you recommend for a neat and reusable coding? – eyesoelectric Jan 13 '14 at 12:57
  • Maybe mixin? Create class with `myNewMethod` (lets call it `MyMixin`), inherit from subclasses from externalLib AND MyMixin, like class `MySubclass(externalLib.Subclass, MyMixin)` – Filip Malczak Jan 13 '14 at 13:04
  • I think the keyword is [trait](http://en.wikipedia.org/wiki/Trait_(computer_programming)), not "wrong". – nmclean Jan 13 '14 at 13:17
  • Does it work only if externalLib.Subclass can be determined? As there are too many subclasses. And also, how should I use this clip of code? Say if I have written some modules which uses those subclasses, and want to add the myNewMethod() calls in those modules? – eyesoelectric Jan 13 '14 at 13:18
  • Please, atempet to the fact that this answer does show a way for the code you asked about to work - but it does not mean it is **the right way to do it**. Fillip calls your attention to that in his comment above. – jsbueno Jan 13 '14 at 13:23
  • I know it is one of the way, and what should I change on my code for a good practice? – eyesoelectric Jan 13 '14 at 13:35
  • @fatfacedw You could dynamically add the mixin to the original superclass's bases ([see here](http://stackoverflow.com/questions/11042424/adding-base-class-to-existing-object-in-python)) to apply it to all the existing subclasses. It will work in other modules as long as you execute this at the entry point of the application before the other modules try to access the new methods. – nmclean Jan 13 '14 at 20:08
2

You are looking to monkeypatch the original class. Because methods are just attributes on a class, you can always add more:

import externalLib as myLib

def myNewMethod(self):
    print(self.name)

myLib.Superclas.myNewMethod = myNewMethod
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343