Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
June 18, 2007 Q: How to return sub class from base class method | ||||
---|---|---|---|---|
| ||||
Hello. I have a class structure as such: > class A { > typeof(this) doSomething (????) { > ... > return this; > } > } > > class B : A { > typeof(this) doSomethingElse (????) { > ... > return this; > } > } > > void main () { > // Fails > B b = (new B()).doSomething (???).doSomethingElse (???); > } The method chain fails as doSomething returns type A. I want to define method doSomething in such a way that it will return the specialized type (B) rather than the base type. I'm currently using a mixin to mixin overriding code: > template doSomethingOverride () { > override typeof(this) doSomething (????) { > super.doSomething (????); > return this; > } > } Is there a way to set the return type as the type instantiated? Thanks, Myron. |
June 18, 2007 Re: Q: How to return sub class from base class method | ||||
---|---|---|---|---|
| ||||
Posted in reply to Myron Alexander | Myron Alexander wrote: > I have a class structure as such: > >> class A { >> typeof(this) doSomething (????) { >> ... >> return this; >> } >> } >> >> class B : A { >> typeof(this) doSomethingElse (????) { >> ... >> return this; >> } >> } >> >> void main () { >> // Fails >> B b = (new B()).doSomething (???).doSomethingElse (???); >> } > > The method chain fails as doSomething returns type A. > > I want to define method doSomething in such a way that it will return the specialized type (B) rather than the base type. > > Is there a way to set the return type as the type instantiated? Yes, you can use CRTP (http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern). class A(T) { T doSomething() { ... return cast(T)this; } } class B(T) : A!(T) { T doSomethingElse() { ... return cast(T)this; } } There might be other (more clever) ways to do this too. Like a mixin for the "selftype" or something. |
June 18, 2007 Re: Q: How to return sub class from base class method | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jari-Matti Mäkelä | Jari-Matti Mäkelä wrote:
>
> Yes, you can use CRTP
> (http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern).
>
> class A(T) {
> T doSomething() {
> ...
> return cast(T)this;
> }
> }
>
> class B(T) : A!(T) {
> T doSomethingElse() {
> ...
> return cast(T)this;
> }
> }
>
> There might be other (more clever) ways to do this too. Like a mixin for
> the "selftype" or something.
Thanks for the suggestion. I am hoping for a solution that does not require me to set a type on instantiation. I just want to write:
B b = (new B()).doSomething (???).doSomethingElse (???);
If the language does not have a way to do it, that's ok, the mixin solution works.
Regards,
Myron.
|
June 18, 2007 Re: Q: How to return sub class from base class method | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jari-Matti Mäkelä | Jari-Matti Mäkelä wrote: > Myron Alexander wrote: > > >>I have a class structure as such: >> >> >>>class A { >>> typeof(this) doSomething (????) { >>> ... >>> return this; >>> } >>>} >>> >>>class B : A { >>> typeof(this) doSomethingElse (????) { >>> ... >>> return this; >>> } >>>} >>> >>>void main () { >>> // Fails >>> B b = (new B()).doSomething (???).doSomethingElse (???); >>>} >> >>The method chain fails as doSomething returns type A. >> >>I want to define method doSomething in such a way that it will return >>the specialized type (B) rather than the base type. >> >>Is there a way to set the return type as the type instantiated? > > > Yes, you can use CRTP > (http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern). > > class A(T) { > T doSomething() { > ... > return cast(T)this; > } > } > > class B(T) : A!(T) { > T doSomethingElse() { > ... > return cast(T)this; > } > } > > There might be other (more clever) ways to do this too. Like a mixin for > the "selftype" or something. I believe B should look like this, if you're using that pattern: class B : A!(B) { B doSomethingElse() { // ... return this; } } Thus, B is derived from a class template to which you pass B as a parameter. This is often used in C++ as a way of emulating mixin-like behavior. Thus, D's template mixins could very well be a better solution. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org |
June 18, 2007 Re: Q: How to return sub class from base class method | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | Kirk McDonald wrote: > Jari-Matti Mäkelä wrote: >> class A(T) { >> T doSomething() { >> ... >> return cast(T)this; >> } >> } >> >> class B(T) : A!(T) { >> T doSomethingElse() { >> ... >> return cast(T)this; >> } >> } >> >> There might be other (more clever) ways to do this too. Like a mixin for >> the "selftype" or something. > > I believe B should look like this, if you're using that pattern: > > class B : A!(B) { > B doSomethingElse() { > // ... > return this; > } > } Actually no - class B was supposed to be in the middle of the hierarchy so class C would have looked like that :) Something like class A(T = A) { ... } class B(T = B) : A!(T) { ... } would have been nice for those non-abstract base classes so they could have been instantiated too, but apparently the compiler didn't want to co-operate this time. > > Thus, B is derived from a class template to which you pass B as a parameter. This is often used in C++ as a way of emulating mixin-like behavior. Thus, D's template mixins could very well be a better solution. > Feel free to create a better solution :) |
June 18, 2007 Re: Q: How to return sub class from base class method | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jari-Matti Mäkelä Attachments: | Jari-Matti Mäkelä wrote:
> Kirk McDonald wrote:
>
>> Jari-Matti Mäkelä wrote:
>>> class A(T) {
>>> T doSomething() {
>>> ...
>>> return cast(T)this;
>>> }
>>> }
>>>
>>> class B(T) : A!(T) {
>>> T doSomethingElse() {
>>> ...
>>> return cast(T)this;
>>> }
>>> }
>>>
>>> There might be other (more clever) ways to do this too. Like a mixin for
>>> the "selftype" or something.
>> I believe B should look like this, if you're using that pattern:
>>
>> class B : A!(B) {
>> B doSomethingElse() {
>> // ...
>> return this;
>> }
>> }
>
> Actually no - class B was supposed to be in the middle of the hierarchy so class C would have looked like that :)
>
> Something like
>
> class A(T = A) { ... }
> class B(T = B) : A!(T) { ... }
>
> would have been nice for those non-abstract base classes so they could have been instantiated too, but apparently the compiler didn't want to co-operate this time.
>
>> Thus, B is derived from a class template to which you pass B as a parameter. This is often used in C++ as a way of emulating mixin-like behavior. Thus, D's template mixins could very well be a better solution.
>>
>
> Feel free to create a better solution :)
Thanks all.
I am happy with the mixin solution, even if I forget to add the mixin, the compiler will generate an error when I try to chain the class methods after the doSomething so it's not a dangerous one at that.
Just for your information, I attached the test source where I am using it. The doSomething method here is called 'initCause'.
Regards,
Myron.
|
Copyright © 1999-2021 by the D Language Foundation