Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decorators versus inheritance

How do you decide between using decorators and inheritance when both are possible?

E.g., this problem has two solutions.

I'm particularly interested in Python.

like image 619
Neil G Avatar asked Jun 20 '11 02:06

Neil G


People also ask

What is difference between decorator and inheritance?

With decorators, responsibilities can be added and removed at run-time simply by attaching and detaching them. In contrast, inheritance requires creating a new class for each additional responsibility (e.g., BorderedScrollableTextView, BorderedTextView).

Does decorator pattern use inheritance?

We use inheritance or composition to extend the behavior of an object but this is done at compile time and its applicable to all the instances of the class.

What is inheritance in design pattern?

Inheritance can be a helpful pattern when you notice that you're defining the same behavior across multiple instances. Back in the example of a program that deals with shapes of various types, you might have a method drawBorder that's being duplicated across multiple different types of shapes.

What is the point of decorators?

A decorator is a design pattern in Python that allows a user to add new functionality to an existing object without modifying its structure. Decorators are usually called before the definition of a function you want to decorate.


1 Answers

Decorators...:

  • ...should be used if what you are trying to do is "wrapping". Wrapping consists of taking something, modifying (or registering it with something), and/or returning a proxy object that behaves "almost exactly" like the original.
  • ...are okay for applying mixin-like behavior, as long as you aren't creating a large stack of proxy objects.
  • ...have an implied "stack" abstraction:

e.g.

@decoA
@decoB
@decoC
def myFunc(...): ...
    ...

Is equivalent to:

def myFunc(...): ...
    ...
myFunc = decoA(decoB(decoC(myFunc)))  #note the *ordering*

Multiple inheritance...:

  • ... is best for adding methods to classes; you cannot use it to decorate functions easily. In this context, it can be used to achieve mixin-like behavior if all you need is a set of "duck-typing style" extra methods.
  • ... may be a bit unwieldy if your problem is not a good match for it, with issues with superclass constructors, etc. For example, the subclasses __init__ method will not be called unless it is called explicitly (via the method-resolution-order protocol)!

To sum up, I would use decorators for mixin-like behavior if they didn't return proxy objects. Some examples would include any decorator which returns the original function, slightly modified (or after registering it somewhere or adding it to some collection).

Things you will often find decorators for (like memoization) are also good candidates, but should be used in moderation if they return proxy objects; the order they are applied matter. And too many decorators on top of one another is using them in a way they aren't intended to be used.

I would consider using inheritance if it was a "classic inheritance problem", or if all I needed for the mixin behavior were methods. A classic inheritance problem is one where you can use the child wherever you could use the parent.

In general, I try to write code where it is not necessary to enhance arbitrary things.

like image 90
ninjagecko Avatar answered Sep 28 '22 00:09

ninjagecko