April 30, 2016 Re: Inheritance of mixin | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Friday, 29 April 2016 at 10:59:20 UTC, Timon Gehr wrote: > The use case isn't rare (it is a quite popular request, at least four independent instances that I remember). > > Having a mixin in all classes in some subtree of the class hierarchy can be a good idea. Of course one can easily do it manually, but it is always nice to get rid of boilerplate. The argument in favour of this feature is even stronger, it also impacts correctness. Both when providing libraries or a large team working within the same framework. Programmer 1: class ComplexAndGenericAbstractBase { ... } Programmer 2: class Car : ComplexAndGenericAbstractBase { ... correctly uses mixin } Programmer 3: class BlueCar : Car { ... no mixin, everything compiles, but is terribly broken at _runtime_(!) } So either P2 needs to remember to prevent anyone from inheriting from 'Car', or P3 needs to type mixin "out of the blue", P2 might not even have documented the need to do so, after all the full doc is in ComplexAndGenericAbstractBase... | |||
April 30, 2016 Re: Inheritance of mixin | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrew Benton | On Saturday, 30 April 2016 at 01:06:18 UTC, Andrew Benton wrote:
> On Friday, 29 April 2016 at 19:11:24 UTC, tsbockman wrote:
>> Rare as in, "effecting only a very small amount of real world code" - not as in "effecting only a very small number of people".
>
> [...]
>
> Additionally, any libraries that provide a base class with a mixin require inheritors to know about that mixin and provide it in their own code.
>
> [...]
It looks like you miss the solution proposed above, using a template this parameter. It's very clear and consise ! Actually the mixin is even not necessary.
| |||
April 30, 2016 Re: Inheritance of mixin | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ed | On Saturday, 30 April 2016 at 22:14:47 UTC, Ed wrote:
> On Saturday, 30 April 2016 at 01:06:18 UTC, Andrew Benton wrote:
>> On Friday, 29 April 2016 at 19:11:24 UTC, tsbockman wrote:
>>> Rare as in, "effecting only a very small amount of real world code" - not as in "effecting only a very small number of people".
>>
>> [...]
>>
>> Additionally, any libraries that provide a base class with a mixin require inheritors to know about that mixin and provide it in their own code.
>>
>> [...]
>
> It looks like you miss the solution proposed above, using a template this parameter. It's very clear and consise ! Actually the mixin is even not necessary.
Unfortunately the solution with the templated "this" creates non-virtual functions. Using the template and the classes in that solution, the following main method produces two UUIDs:
void main() {
Base a = new Base(), b = new Inheritor();
a.writeName.writeln;
b.writeName.writeln;
}
which is very different from the output that we would want by having the specialization of Base.
| |||
May 02, 2016 Re: Inheritance of mixin | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrew Benton | On Saturday, 30 April 2016 at 01:06:18 UTC, Andrew Benton wrote:
> Additionally, any libraries that provide a base class with a mixin require inheritors to know about that mixin and provide it in their own code. It certainly isn't going to happen in every case, but if the needed functionality is provided by mixins, then users of the library could have problems.
I spent a while trying to figure out how to automatically verify that a mixin required by a class hierarchy is included in all derived classes, and failed to come up with a general purpose solution. (I found a partial solution involving a `this T` templatized constructor, but it had a lot of problems.) So, I agree now that this is a problem worth solving.
It could be fixed by extending template mixins as you and others have proposed.
Another possible solution would be to fix `this T` template functions to be virtual, and automatically generate an override for each derived class. This would directly solve the most common use case, and also provide an (awkward) way to automatically verify mixin inclusion in derived classes for more complex scenarios.
| |||
May 02, 2016 Re: Inheritance of mixin | ||||
|---|---|---|---|---|
| ||||
Posted in reply to tsbockman | On Monday, 2 May 2016 at 16:41:01 UTC, tsbockman wrote: > On Saturday, 30 April 2016 at 01:06:18 UTC, Andrew Benton wrote: >> Additionally, any libraries that provide a base class with a mixin require inheritors to know about that mixin and provide it in their own code. It certainly isn't going to happen in every case, but if the needed functionality is provided by mixins, then users of the library could have problems. > > I spent a while trying to figure out how to automatically verify that a mixin required by a class hierarchy is included in all derived classes, and failed to come up with a general purpose solution. (I found a partial solution involving a `this T` templatized constructor, but it had a lot of problems.) So, I agree now that this is a problem worth solving. > > It could be fixed by extending template mixins as you and others have proposed. > > Another possible solution would be to fix `this T` template functions to be virtual, and automatically generate an override for each derived class. This would directly solve the most common use case, and also provide an (awkward) way to automatically verify mixin inclusion in derived classes for more complex scenarios. templatized functions in classes will never be virtual and there's a technical reason explained here: https://issues.dlang.org/show_bug.cgi?id=1657#c1 (TL;DR: it's problematic to generate the vtbl) In some cases, remixing a template in each sub classes works (for example here https://github.com/Mihail-K/witchcraft#caveats), in some cases a template with a template this parameter works but **here** it's true that among the workarounds, none is conform with the OOP principles as noted in this answer: https://forum.dlang.org/post/pacfkkgazpqaodsbqoss@forum.dlang.org. | |||
May 02, 2016 Re: Inheritance of mixin | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Basile B. | On Monday, 2 May 2016 at 17:37:14 UTC, Basile B. wrote:
> templatized functions in classes will never be virtual and there's a technical reason explained here:
>
> https://issues.dlang.org/show_bug.cgi?id=1657#c1
>
> (TL;DR: it's problematic to generate the vtbl)
I understand why template methods in general shouldn't be virtual. `this T` is special though, and a method with no other template parameters could be lowered to an ordinary virtual method in a straightforward fashion.
Basically, this:
class A
{
string foo(this T)() { return T.stringof; }
}
class B : A { }
Could be lowered to this:
class A
{
string foo() { return A.stringof; }
}
class B : A
{
override string foo() { return B.stringof; }
}
That's not how it works currently, but there is no technical reason it couldn't be *made* to work that way.
Obviously this would be a breaking change though; `this T` template methods that should retain the current behaviour could be marked `final`. (Given that non-template methods are virtual by default, I think requiring template methods to be marked `final` would improve code clarity, anyway.)
| |||
May 02, 2016 Re: Inheritance of mixin | ||||
|---|---|---|---|---|
| ||||
Posted in reply to tsbockman | On Monday, 2 May 2016 at 17:50:50 UTC, tsbockman wrote:
> On Monday, 2 May 2016 at 17:37:14 UTC, Basile B. wrote:
>> templatized functions in classes will never be virtual and there's a technical reason explained here:
>>
>> https://issues.dlang.org/show_bug.cgi?id=1657#c1
>>
>> (TL;DR: it's problematic to generate the vtbl)
>
> [...]
>
> That's not how it works currently, but there is no technical reason it couldn't be *made* to work that way.
>
> Obviously this would be a breaking change though; `this T` template methods that should retain the current behaviour could be marked `final`. (Given that non-template methods are virtual by default, I think requiring template methods to be marked `final` would improve code clarity, anyway.)
Not that much a breaking change. Perhaps a slight decrease of the performances...and even not indeed: in all the previous usages devirtualization of the will be possible.
| |||
May 02, 2016 Re: Inheritance of mixin | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Basile B. | On Monday, 2 May 2016 at 18:14:29 UTC, Basile B. wrote:
> On Monday, 2 May 2016 at 17:50:50 UTC, tsbockman wrote:
>> [...]
>>
>> That's not how it works currently, but there is no technical reason it couldn't be *made* to work that way.
>>
>> Obviously this would be a breaking change though; `this T` template methods that should retain the current behaviour could be marked `final`. (Given that non-template methods are virtual by default, I think requiring template methods to be marked `final` would improve code clarity, anyway.)
>
> Not that much a breaking change. Perhaps a slight decrease of the performances...and even not indeed: in all the previous usages devirtualization of the will be possible.
It's a significant breaking change, because the purpose of it is to change the output of Andrew Benton's earlier example:
void main() {
Base a = new Base(), b = new Inheritor();
a.writeName.writeln;
b.writeName.writeln; // The semantics of this line changes.
}
Currently, the above will call the `Base` version of `writeName()` for `b`. With my proposal, it would call the `Inheritor()` version.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply