15

I have a function in a superclass that returns a new version of itself. I have a subclass of this super that inherits the particular function, but would rather it return a new version of the subclass. How do I code it so that when the function call is from the parent, it returns a version of the parent, but when it is called from the child, it returns a new version of the child?

user592419
  • 5,103
  • 9
  • 42
  • 67
  • Why do you have to distinguish the types. One feature of inheritance is that an instance of a subclass may act as an instance of its super class. – Oben Sonne Oct 20 '11 at 19:10
  • 3
    The function lives in the parent. It returns a new object. If I return an instance of the parent, then it doesnt get access to the child's functions. But I can't just return the child because then no other child could use this function (and the parent cant either really). So I want to return an instance of whatever called it. – user592419 Oct 20 '11 at 19:16

1 Answers1

10

If new does not depend on self, use a classmethod:

class Parent(object):
    @classmethod
    def new(cls,*args,**kwargs):
        return cls(*args,**kwargs)
class Child(Parent): pass

p=Parent()
p2=p.new()
assert isinstance(p2,Parent)
c=Child()
c2=c.new()
assert isinstance(c2,Child)

Or, if new does depend on self, use type(self) to determine self's class:

class Parent(object):
    def new(self,*args,**kwargs):
        # use `self` in some way to perhaps change `args` and/or `kwargs`
        return type(self)(*args,**kwargs)
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • In which situations should the first method be used if the second will also work in that case? Just to make it clearer to readers that `new` doesn't mutate `self` and/or `args`/`kwargs`? – nivk Oct 30 '17 at 18:19
  • @nivk: One of the main uses of classmethod is [to define "alternative constructors"](https://stackoverflow.com/a/1950927/190597). Insofar as this is an understood convention, it is helpful to others who read your code for you to follow this convention too. – unutbu Oct 30 '17 at 19:34
  • In this case seems like the second method should be preferred due to its flexibility. I don't think OP needs an alternative constructor in the sense shown in the link (and my use case that brought me here doesn't either). Is there something I'm missing that should prefer the first method? – nivk Oct 30 '17 at 20:26
  • I think we are in agreement on matters of the fact, but not on taste. De gustibus non est disputandum... – unutbu Oct 30 '17 at 23:58
  • 1
    What can I do if I do not have control over the implementation of the Parent Class? For example, if I happen to inherit from built-in Int class? – mbpaulus Oct 29 '18 at 17:25
  • @mexmex: You can still subclass `int` by overriding `__new__`. See [here](https://jfine-python-classes.readthedocs.io/en/latest/subclass-int.html#emulating-bool-using-new) for example. If you are trying to override `__add__`, you may be able to achieve the effect you want [this way](https://gist.github.com/unutbu/2be784436f1495015b16b0c6eb5f21f1). Or, if I'm not understanding your situation properly, please post it as a new question. – unutbu Oct 29 '18 at 18:21
  • @unutbu. Thank you. I'm not sure if my issue merits a post, maybe you can help decide. I want to subclass int (to create a custom class as a representation for some set arithmetic). Right now I am not using inheritance, but just create a custom class with a property (self.int) that stores a respective int. Then I define all the magic methods (__add__, etc.), to operate on the self.int property and return an instance of my custom class with the result. Can inheritance be used to spare defining self.int and all magic methods, but still return MyInt(3) and not 3 when MyInt(1)+MyInt(2)? – mbpaulus Oct 29 '18 at 22:03
  • Even if you subclassed `int`, IIUC, you'd still need to override magic methods, so I'm not sure there is much to gain by subclassing `int`. If all of `int`s magic methods have to be changed, there'd be nothing to gain through inheritance. Moreover the [Liskov substitution principle](https://stackoverflow.com/q/56860/190597) suggests "objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program." Since that doesn't appear to be the case here, you probably -- again, IIUC -- should not make `MyInt` a subclass of `int`. – unutbu Oct 30 '18 at 01:08