C++ Logo

std-proposals

Advanced search

Re: Add a specialized "Extension" concept to the inheritance syntax

From: Ofri Sadowsky <sadowsky.o.phd_at_[hidden]>
Date: Sun, 19 May 2019 19:38:31 +0300
Fairly said.

I have no room or time here to describe my concrete case, or to discuss the
merits or lack thereof of inheritance. For better or worse, C++ continues
to support it, it is taught in many schools, and I, for one, do find some
use for it.

One does not have to support the request, but I would not have dismissed it
simply because inheritance is considered evil. Unless there is a plan to
drive inheritance out of C++.

Sincerely,

OS

בתאריך יום א׳, 19 במאי 2019, 19:20, מאת Tony V E ‏<tvaneerd_at_[hidden]>:

> Yes, Herb's solution does not compose well in a multilevel hierarchy.
>
> And yes, what you describe is a fairly common pattern, but I typically
> find it to be an anti pattern. Inheritance with partial implementation at
> each level is also a anti-pattern, IMO.
>
> Sure a car is a vehicle, and a truck is just a car with the trunk replaced
> with an open bed and stronger frame, and a cube van is just a truck with ‎a
> cube instead of the open bed, etc.
>
> But I'd rather break those components into mixin classes or member
> variables, and then just derive cub van straight from vehicle, and give it
> a cube member variable.
>
> https://en.wikipedia.org/wiki/Composition_over_inheritance
>
> Or better, just don't do inheritance at all: "Inheritance is the base
> class of evil" - Sean Parent
>
> https://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil
>
> But, yes, sometimes inheriting and calling the base which calls its base,
> etc, is a pattern that works. I just don't think it is important enough to
> be a keyword.
>
>
> Sent from my BlackBerry portable Babbage Device
> *From: *Ofri Sadowsky
> *Sent: *Sunday, May 19, 2019 11:58 AM
> *To: *std-proposals_at_[hidden]; Tony V E
> *Subject: *Re: [std-proposals] Add a specialized "Extension" concept to
> the inheritance syntax
>
> It looks like the experience that I believed was common is no as common as
> I thought. So let me try to re-explain.
>
> Suppose that class Base0 has a setup() method which acquires some
> resources, and a cleanup() method which releases them. Before getting to
> the difficult cases, let's assume a simple case in which setup() subscribes
> to some event in the larger application framework, and cleanup()
> unsubscribes.
>
> To be closer to Sutter's guidelines, let's suppose that setup() and
> cleanup() both break down to a public, nonvirtual method setup()/cleanup()
> and another private or protected virtual method, say onSetup()/onCleanup()
> which is to be overridden by derived classes. And, further, let's suppose
> that class Base0 defines this interface, and class Base1 (public Base0)
> uses it to define the subscription operations.
>
> Now, let's examine a class Derived (public Base1), which also has to
> perform some onSetup() and onCleanup() tasks, like subscription to more
> framework events. However, it also must ensure that its base class, Base1,
> is properly set up itself before Derived even begins to set itself up.
> Since Derived does not know the implementation of Base1::onSetup(), it must
> be able to call _some_ Base1 method. Continuing this down inheritance
> line, rather than making up new method names in each base class just so
> that the derived classes would be able to invoke the base's onSetup()
> through the interface, would it not make sense that each derived class
> would *extend* (I am deliberately not suggesting to _call_) the base
> class's onSetup() method?
>
> This is not a pattern (or anti-pattern, if you happen to dislike it) that
> I made up myself. I encountered it in various framework libraries, and, at
> least, the concept makes sense to me.
>
> The solution that these libraries used was, indeed, a direct call from the
> beginning (in the case of tail extension) or end (in the case of head
> extension) of the _overriding_ derived method to the same method in the
> base class. Maybe there is a better solution for this, but this is how it
> was done.
>
> To stress the point: the issue is not about being or not being able to
> call base virtual methods from derived classes. It is about the need to
> scale up by extension operations such as setup()/cleanup(). This is why I
> am presenting it as new declarative syntax. I do believe that such a
> syntax would enable better solutions given automatically by the compiler,
> as in the case of virtual diamond multiple inheritance. And I am convinced
> that the need is a real one.
>
> Sincerely
>
> Ofri Sadowsky
>
>
> On Sat, May 18, 2019 at 1:49 AM Tony V E <tvaneerd_at_[hidden]> wrote:
>
>>
>>
>> This most like is worth a read, from Herb Sutter:
>> http://www.gotw.ca/publications/mill18.htm
>>
>>
>>
>>
>> On Fri, May 17, 2019 at 5:24 AM Ofri Sadowsky via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>> This post is based on an experience which, I believe, is shared by many,
>>> having to do with the concept of "extending" a base class rather than
>>> "overriding" its functionality. Here are two directions for this concept.
>>>
>>> First: It is common in class methods that perform some setup or cleanup
>>> operations to require a derived class to invoke the corresponding base
>>> class method, as in the following manner.
>>>
>>> class Base
>>> {
>>> public:
>>> virtual void setup()
>>> {
>>> // do some setup
>>> }
>>>
>>> virtual void cleanup()
>>> {
>>> // do some cleanup
>>> }
>>> };
>>>
>>> class Derived : public Base
>>> {
>>> public
>>> void setup() override
>>> {
>>> Base::setup();
>>> // do my own setup
>>> }
>>>
>>> void cleanup() override
>>> {
>>> // do my own cleanup
>>> Base::cleanup();
>>> }
>>> };
>>>
>>> In current language, this is the only way to achieve it ,and it requires
>>> the developer to explicitly make the call to the base class method, with
>>> the risk of missing it. In principle, the existing compiler mechanism
>>> could also support something such as the following.
>>>
>>> class Base
>>> {
>>> public:
>>> tail_extensible void setup()
>>> {
>>> // do some setup
>>> }
>>>
>>> head_extensible void cleanup()
>>> {
>>> // do some cleanup
>>> }
>>> };
>>>
>>> class Derived
>>> {
>>> public:
>>> void setup() extension
>>> {
>>> // Base::setup() is called automatically
>>> // do my own setup
>>> }
>>>
>>> void cleanup() extension
>>> {
>>> // do my own cleanup
>>> // Base::cleanup is called automatically
>>> }
>>> };
>>>
>>> Semantically, the tail_extensible is similar to a virtual function,
>>> including an identical signature for the base and derived method, and all
>>> that is left is to forward the arguments passed to the derived method onto
>>> the base by using the regular signature rules (i.e by-value will be
>>> forwarded by value, by const reference will be forwarded as const
>>> reference, etc.).
>>>
>>>
>>>
>>> Second: It sometimes happens that I want to extend an existing class
>>> with functionality only, but not with new members. For example, I want to
>>> have a class that has all the functionality of a std::string and then some
>>> of my own. This can be accomplished using composition or, probably more
>>> simply, through inheritance. However, my class only needs the members of
>>> std::string.
>>>
>>> In the current language, I'd have to manually write all the constructors
>>> to allow my class to be constructed from a string, or from anything that
>>> constructs a string, assigned from a string, etc. Moreover, I'd have to
>>> add the move constructor etc., whose defaults expire as soon as I define
>>> the regular constructors. But all this is not really necessary, and
>>> furthermore creates a risk of forgetting to do it.
>>>
>>> Suppose we had an "extends" keyword whose semantics is: the extending
>>> class cannot define new members (maybe more relaxed for static members),
>>> and in return it does not have to specify all the mechanism of construction
>>> and assignment, which is inherited from the base class.
>>>
>>> class MySpecialString : public extends std::string
>>> {
>>> public:
>>> // only new methods or overrides from the base, no members, no
>>> constructors,
>>> // no assignments, no operator overloading
>>> };
>>>
>>> This does pose some potential complications, such as would and how
>>> overloaded operators be included in the extension semantics, what about
>>> destructors? what to do with multiple extension (corresponding to multiple
>>> inheritance) an so on. But I think that consistent rules can be developed
>>> for this.
>>>
>>>
>>>
>>> All this is more about simplifying a developer's life, reducing
>>> boilerplate and making safer code. It's replacing what would be done
>>> manually with a declarative form that implies clear semantics. I'd like to
>>> see this standardized.
>>>
>>> Regards
>>>
>>> Ofri Sadowsky
>>>
>>> --
>>> Ofri Sadowsky, PhD
>>> Computer Science Consulting and Training
>>> 7 Carmel St., #37
>>> Rehovot 7630507
>>> Israel
>>>
>>> Tel: +972-77-3436003
>>> Mob: +972-54-3113572
>>> --
>>> Std-Proposals mailing list
>>> Std-Proposals_at_[hidden]
>>> http://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>
>>
>>
>> --
>> Be seeing you,
>> Tony
>>
>
>
> --
> Ofri Sadowsky, PhD
> Computer Science Consulting and Training
> 7 Carmel St., #37
> Rehovot 76305
> Israel
>
> Tel: +972-77-3436003
> Mob: +972-54-3113572
>
>
>

Received on 2019-05-19 11:40:26