digitalmars.D.learn - Q: How to return sub class from base class method
- Myron Alexander <someone somewhere.com> Jun 17 2007
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= <jmjmak utu.fi.invalid> Jun 17 2007
- Myron Alexander <someone somewhere.com> Jun 17 2007
- Kirk McDonald <kirklin.mcdonald gmail.com> Jun 17 2007
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.
Jun 17 2007
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.
Jun 17 2007
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.
Jun 17 2007
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
Jun 17 2007
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 :)
Jun 17 2007
Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit 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.
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.
Jun 18 2007









Myron Alexander <someone somewhere.com> 