[Python-ideas] The prohibition overrides the class method

Andrew Barnert abarnert at yahoo.com
Mon Nov 16 21:21:28 EST 2015


On Nov 16, 2015, at 16:12, Michael Selik <mike at selik.org> wrote:
> 
> Thanks, Ian, I missed that detail.
> 
> While my initial thought was that name mangling would achieve the desired level of subclassing-clumsiness defense. As below...
> 
>     # using 2 steps instead of 3, for brevity
> 
>     class Envelope:
>         def prepare(self):
>             print('omnibus!')
> 
>     class Child(Envelope):
> 
>         def stuff(self):
>             print('step 1')
>         __stuff = stuff
> 
>         def seal(self):
>             print('step 2')
>         __seal = seal
> 
>         def prepare(self):
>             self.__stuff()
>             self.__seal()
> 
> 
> The post on StackExchange added the extra wrinkle that both classes have C++ virtual functions, kind-of like this...
> 
>     from abc import ABC, abstractmethod
> 
>     class Envelope(ABC):
> 
>         def something_useful(self):
>             ''' I'd normally avoid tricky inheritance
>             but there must be some really useful code
>             in here that I don't want to refactor
>             '''
> 
>         @abstractmethod
>         def prepare(self):
>             pass
> 
> 
>     class Child(Envelope):
> 
>         @abstractmethod
>         def stuff(self):
>             print('step 1')
> 
>         @abstractmethod
>         def seal(self):
>             print('step 2')
> 
>         def prepare(self):
>             'should be FINAL, Override at your OWN PERIL'
>             self.stuff()
>             self.seal()
> 
> This contrived scenario seems better resolved by refactoring the `Envelope` class. Moreover, I don't understand why the `Child` class would exist at all. Why override `prepare` only to create more abstract methods?

Apparently, because they want to use the strategy pattern, twice, but in a way that gets none of the advantages of that pattern.

To actually get the benefits, those new abstract methods would not be in Child; instead, you'd create a new EnvelopePrepaper interface that Child uses. Why can't you just merge the EnvelopePreparer into Child itself? Because then you lose all the decoupling benefits that the strategy pattern is meant to provide, and you add new problems in that a single class now has multiple separate interfaces that can accidentally step on each other's toes. In fact, what they clearly wanted was for Envelope to use a preparer strategy, and for Child to _be_ such a preparer strategy that itself uses a 2-stage-preparer strategy, and for other people to implement 2-stage-preparer strategies. But then they've merged both interfaces into the class that uses those strategies instead for no good reason. If you fix either of those problems, or just use a simpler design instead of misusing strategy, or even if you only misuse strategy once instead of multiple times, the problem wouldn't arise.

In other words, it's a subset of exactly the problem I suggested before seeing the example: If you want to inherit from a class, you have to know that class's interface, because you're promising to implement it. This design forces users to inherit from a class whose interface they don't know, and then hopes for a new language feature to hide one of the symptoms of that problem instead of fixing the problem.

>> On Mon, Nov 16, 2015 at 6:40 PM Ian Kelly <ian.g.kelly at gmail.com> wrote:
>> On Nov 16, 2015 4:15 PM, "Michael Selik" <mike at selik.org> wrote:
>> >
>> > For that envelopes example on StackExchange, I'd probably use name mangling to reduce chances of subclassing mistakes and have prepare() call stuff(), seal(), stamp() in the correct order or whatever those were. I'm not sold in the need for "final".
>> 
>> Name mangling would not work in that example. The prepare method is defined by a base class and overridden in a subclass; it is the subclass that wishes to declare the method final. Name mangling would obstruct overriding the method at all, which would be a problem for the base class that invites the method to be overridden.
>> _______________________________________________
>> Python-ideas mailing list
>> Python-ideas at python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20151116/38e1dc72/attachment-0001.html>


More information about the Python-ideas mailing list