Thread overview | ||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 24, 2014 Cumulative | ||||
---|---|---|---|---|
| ||||
25 years ago, when I was trying to write some sort of library to go with Walter's C++ compiler, I had a wish, and it still pops into my head from time to time. What I wanted was functions that were declared in a base class as 'cumulative', or something similar. They would have been generally like virtual functions, except that any derived class that wanted to do something extra - as opposed to something different, would simply define an 'extend', and just specify the extra code. The compiler would then automatically add a call to the same function in whatever base class last defined or extended the method. extend void foo() // Declared in base class as cumulative void foo() { (cast(BaseClass) this).foo(); // Compiler does this for you // similar to changing a light bulb ;=) // the extra stuff } I think also that it might be necessary for the base class function to return on behalf of the derived method as opposed to to it. Does this make any sense? Steve |
February 24, 2014 Re: Cumulative | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Teale | On Monday, 24 February 2014 at 08:41:06 UTC, Steve Teale wrote:
> 25 years ago, when I was trying to write some sort of library to go with Walter's C++ compiler, I had a wish, and it still pops into my head from time to time.
>
> What I wanted was functions that were declared in a base class as 'cumulative', or something similar. They would have been generally like virtual functions, except that any derived class that wanted to do something extra - as opposed to something different, would simply define an 'extend', and just specify the extra code. The compiler would then automatically add a call to the same function in whatever base class last defined or extended the method.
>
> extend void foo() // Declared in base class as cumulative void foo()
> {
> (cast(BaseClass) this).foo(); // Compiler does this for you
> // similar to changing a light bulb ;=)
>
> // the extra stuff
> }
>
> I think also that it might be necessary for the base class function to return on behalf of the derived method as opposed to to it.
>
> Does this make any sense?
>
> Steve
Sorry, I had two foo()s in the 'example'. What I meant was
extend void foo() // Declared in base class as cumulative
{
|
February 24, 2014 Re: Cumulative | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Teale | On Monday, 24 February 2014 at 08:41:06 UTC, Steve Teale wrote:
> 25 years ago, when I was trying to write some sort of library to go with Walter's C++ compiler, I had a wish, and it still pops into my head from time to time.
>
> What I wanted was functions that were declared in a base class as 'cumulative', or something similar. They would have been generally like virtual functions, except that any derived class that wanted to do something extra - as opposed to something different, would simply define an 'extend', and just specify the extra code. The compiler would then automatically add a call to the same function in whatever base class last defined or extended the method.
>
> extend void foo() // Declared in base class as cumulative void foo()
> {
> (cast(BaseClass) this).foo(); // Compiler does this for you
> // similar to changing a light bulb ;=)
>
> // the extra stuff
> }
>
> I think also that it might be necessary for the base class function to return on behalf of the derived method as opposed to to it.
>
> Does this make any sense?
>
> Steve
This exists but it's not automatic.
class Foo
{
void foo()
{
...
}
}
Class Bar : Foo
{
override void foo()
{
super.foo(); // Call parents method.
...
}
}
|
February 24, 2014 Re: Cumulative | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Teale | On Monday, 24 February 2014 at 08:41:06 UTC, Steve Teale wrote:
> 25 years ago, when I was trying to write some sort of library to go with Walter's C++ compiler, I had a wish, and it still pops into my head from time to time.
>
> What I wanted was functions that were declared in a base class as 'cumulative', or something similar. They would have been generally like virtual functions, except that any derived class that wanted to do something extra - as opposed to something different, would simply define an 'extend', and just specify the extra code. The compiler would then automatically add a call to the same function in whatever base class last defined or extended the method.
>
> extend void foo() // Declared in base class as cumulative void foo()
> {
> (cast(BaseClass) this).foo(); // Compiler does this for you
> // similar to changing a light bulb ;=)
>
> // the extra stuff
> }
>
> I think also that it might be necessary for the base class function to return on behalf of the derived method as opposed to to it.
>
> Does this make any sense?
>
> Steve
Sounds a little like the :after mechanism of the Common Lisp Object System (CLOS). They also have :before, if your extra code should run before the super-call. The third variant is :around, which is like the default overwriting in D et. al.
|
February 24, 2014 Re: Cumulative | ||||
---|---|---|---|---|
| ||||
Posted in reply to Gary Willoughby | On Monday, 24 February 2014 at 08:55:02 UTC, Gary Willoughby wrote:
> On Monday, 24 February 2014 at 08:41:06 UTC, Steve Teale wrote:
>> What I wanted was functions that were declared in a base class as 'cumulative', or something similar. They would have been generally like virtual functions, except that any derived class that wanted to do something extra - as opposed to something different, would simply define an 'extend', and just specify the extra code. The compiler would then automatically add a call to the same function in whatever base class last defined or extended the method.
>
> This exists but it's not automatic.
I think the point is that the super.foo() call is enforced.
Is it possible to write a @cumulative annotation to detect missing calls? Example:
class Base {
@cumulative void foo() {}
}
class Bar : Base {
void foo() {} // compile error, no super.foo() call
}
It should probably get another name like @overrideExtends.
|
February 24, 2014 Re: Cumulative | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Teale | On Monday, 24 February 2014 at 08:41:06 UTC, Steve Teale wrote:
> 25 years ago, when I was trying to write some sort of library to go with Walter's C++ compiler, I had a wish, and it still pops into my head from time to time.
>
> What I wanted was functions that were declared in a base class as 'cumulative', or something similar. They would have been generally like virtual functions, except that any derived class that wanted to do something extra - as opposed to something different, would simply define an 'extend', and just specify the extra code. The compiler would then automatically add a call to the same function in whatever base class last defined or extended the method.
>
> extend void foo() // Declared in base class as cumulative void foo()
> {
> (cast(BaseClass) this).foo(); // Compiler does this for you
> // similar to changing a light bulb ;=)
>
> // the extra stuff
> }
>
> I think also that it might be necessary for the base class function to return on behalf of the derived method as opposed to to it.
>
> Does this make any sense?
>
> Steve
This is something that I have wished for as well. If it was automatically inserted, it would only make sense for it to be useable on functions with no return and no arguments. If it was just enforcement then it wouldn't matter.
Something that does do this currently is default constructors.
|
February 25, 2014 Re: Cumulative | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Teale | On 2/24/2014 3:41 AM, Steve Teale wrote:
>
> extend void foo() // Declared in base class as cumulative void foo()
> {
> (cast(BaseClass) this).foo(); // Compiler does this for you
> // similar to changing a light bulb ;=)
>
> // the extra stuff
> }
>
> I think also that it might be necessary for the base class function to
> return on behalf of the derived method as opposed to to it.
>
> Does this make any sense?
>
I've often wished for something like that when working on OO-heavy stuff. Some virtual funcs are intended to always be called by all overriding functions, but without a way to enforce that, it becomes a scary error-prone choice of API design. And trying to design your way around that limitation can be a pain.
|
February 25, 2014 Re: Cumulative | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Teale | Maybe: ---- extend void foo() { ... } ---- would force you to use super.foo() and otherwise gives an error? ---- class Foo { void foo() { // ... } } class Bar : Foo { extend void foo() { // compiler will force you (opposed to override) that you call super.foo() but it isn't important where. You can call it at the end or at the start or wherever you wish. } } ---- Maybe we could also reduce the super.FUNCTION with "super" as for base class constructors. Or to distinguish we could name it "base": ---- class Foo { void foo() { // ... } } class Bar : Foo { extend void foo() { base(); /// will be rewritten to super.foo(); } } ---- The latter is of course for the "lazy" people. :) |
February 25, 2014 Re: Cumulative | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | On Tuesday, 25 February 2014 at 00:18:47 UTC, Namespace wrote:
> Maybe:
> ----
> extend void foo() { ... }
> ----
> would force you to use super.foo() and otherwise gives an error?
>
> ----
> class Foo {
> void foo() {
> // ...
> }
> }
>
> class Bar : Foo {
> extend void foo() {
> // compiler will force you (opposed to override) that you call super.foo() but it isn't important where. You can call it at the end or at the start or wherever you wish.
>
> }
> }
> ----
>
> Maybe we could also reduce the super.FUNCTION with "super" as for base class constructors. Or to distinguish we could name it "base":
>
> ----
> class Foo {
> void foo() {
> // ...
> }
> }
>
> class Bar : Foo {
> extend void foo() {
> base(); /// will be rewritten to super.foo();
> }
> }
> ----
>
> The latter is of course for the "lazy" people. :)
This is not good enough, this makes the "extend" optional on overridden functions. What it needs to be is a way to ensure that if your function is overridden by a base class that it is guaranteed to be called by the new function.
Something like this
class A
{
extendable void foo(){}
}
class B : A
{
override void foo(){}// compilation error, super.foo not called
}
This makes it non-optional. You have to call super.foo if you want to override foo.
Also, in some cases it is not enough just to ensure that it is called, some times you will want to make sure that it is called at the beginning or end of the function. Though this is harder to get right, not really sure how it would work with returns.
Also I think it would make sense for something like this to be transitive. For instance in the above example, the new foo should also be extendable or else the guarantee breaks.
|
February 25, 2014 Re: Cumulative | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tofu Ninja | On Tuesday, 25 February 2014 at 00:55:55 UTC, Tofu Ninja wrote:
> Also, in some cases it is not enough just to ensure that it is called, some times you will want to make sure that it is called at the beginning or end of the function. Though this is harder to get right, not really sure how it would work with returns.
In the case where it would be needed to be called at the beginning or the end of the new method. The compiler might be able to implicitly add it in itself, similar to how super(); is implicitly added to the beginning of overridden constructors.
|
Copyright © 1999-2021 by the D Language Foundation