简体   繁体   中英

Question about python and classes

I have a base class and a few derived in Python:

class Base:
   def Foo(self):
      pass

# First derived class
class Der1(Base):
   def OwnFoo(self):
      # Do something 1
   def OwnFoo2(self):
      # Do something 2

   def Foo(self):
      # Do something 3

# Second derived class
class Der2(Base):
   def OwnFoo(self):
      # Do something 1
   def OwnFoo2(self):
      # Do something 2

   def Foo(self):
      # Do something 3

The question is:

I have some predefined code in Der1 . Almost all functions from Der2 do the same. How can I write this with less code?

I can't add that code to the parent. Parent class shouldn't be touched.

For example, Der2.OwnFoo does the same as Der1.OwnFoo , maybe there is some construction in python just to call OwnFoo from first class and not to write that code again?


I can't change the parent of Der1 and Der2 ! It should be Base .

Since you can't change the inheritance structure, make a helper class that contains the common code and include it by composition rather than inheritance.

# Common code goes in this new class
class DerHelper:
    def __init__(self, parent):
        self._parent = parent
    def OwnFoo(self):
        print 'Do something 1', self._parent
    def OwnFoo2(self):
        print 'Do something 2', self._parent
    def Foo(self):
        print 'Do something 3', self._parent

# First derived class
class Der1(Base):
    def __init__(self):
        # include helper class by composition
        self._helper = DerHelper('Der1')
    def OwnFoo(self):
        self._helper.OwnFoo()
    def OwnFoo2(self):
        self._helper.OwnFoo2()
    def Foo(self):
        self._helper.Foo()

# Second derived class
class Der2(Base):
    def __init__(self):
        # include helper class by composition
        self._helper = DerHelper('Der2')
    def OwnFoo(self):
        self._helper.OwnFoo()
    def OwnFoo2(self):
        self._helper.OwnFoo2()
    def Foo(self):
        self._helper.Foo()

Of course, you could pass a reference to the parent instead of a string. I just did it this way for demonstration purposes.

Usage:

d = Der1()
d.OwnFoo()
d.OwnFoo2()
d.Foo()

d = Der2()
d.OwnFoo()
d.OwnFoo2()
d.Foo()

Output:

Do something 1 Der1
Do something 2 Der1
Do something 3 Der1
Do something 1 Der2
Do something 2 Der2
Do something 3 Der2

Make Der2 a subclass of Der1 and you're done.

class Base:
   def Foo(self):
      pass

# First derived class
class Der1(Base):
   def OwnFoo(self):
      # Do something 1
   def OwnFoo2(self):
      # Do something 2

   def Foo(self):
      # Do something 3

# Second derived class (subclasses Der1)
class Der2(Der1):
   pass

Any behavior within Der2 you'd like to specialize can added within the class definition. If you create a new method of the same name in Der2 (eg Der2.OwnFoo() ), then it will overload the default method that is inherited from Der1 .

EDIT: If you can't change the parent, put all of the behavior you want to inherit in the base class keeping in mind that you can overload or customize any of the methods in the subclasses.

In code:

# Base class
class Base:
    def Foo1(self):
        # Do something 1
    def Foo2(self):
        # Do something 2
    def Foo(self):
        # Do something 3

# First derived class, inherits everything from Base
class Der1(Base):
    pass

# Second derived class
class Der2(Base):
    pass  

There is a "trick" you can do to call the original method inherited from the parent, capture the return value and then customize the behavior. This will only work if the method actually returns a value, and can be dangerous if the method manipulates attributes within the class, unless that's what you want and expect it.

In code:

# Second derived class, with customized methods
class Der2(Base):
    # Anything that is not explicitly define is inherited from parent
    # as-is.

    def Foo(self):
        # My Foo() overloads Base.Foo() inherited from parent class. 
        # Do something "special" 3

    def Foo1(self):
        # Calls parent Base.Foo1() and then manipulates return data.
        base_output = Base.Foo1(self)
        # Do something "special" 1 with 'base_output'

Is this a homework?

Look at the first line of Der2 :

class Der2(Base):

What says what is its parent (eg a class it descends and herits methods and attributes from)? How could you change this?

If Der1 and Der2 share a lot of code, then you should put that in a superclass; since Base cannot be touched, introduce a class in between:

class Der(Base):
    def OwnFoo(self):
        ...

class Der1(Der):
    ...

class Der2(Der):
    ...

(Depending on you class hierachy, the "derive Der2 from Der1 " option that others recommend may also be valid.)

如何使Der2子类Der1

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