Reputation: 11963
Many of the methods inside my class would return this;
so that i can call multiple functions within one line. something like a.method1().method2().method3();
problem arise when i try to make a base class. if I make a method to return type T
inside the base class, then i can no longer return this;
since the base class type is not T
. I can't just make the return type as the base class since there are many more methods that are available on the inherited class that are not in the base class. How can i solve this problem?
Sample code:
public class baseClass<T>
{
public T method1()
{
//Do stuffs
return this;//doesnt work
}
}
public class inheritedClass:baseClass<inheritedClass>
{
public inheritedClass method2()
{
//Do stuffs
return this;
}
}
Upvotes: 0
Views: 163
Reputation: 11559
May be this
public abstract class BaseClass<T> where T : BaseClass<T>
{
public T Method1()
{
//Do stuffs
// We are sure any instance of this class is T : BaseClass<T>.
// Only exception might be direct instance of BaseClass<T> and that's why we made BaseClass abstract.
return (T)this;
}
}
public class InheritedClass : BaseClass<InheritedClass>
{
public InheritedClass Method2()
{
//Do stuffs
return this;
}
}
Two things changed. First, we are still casting but doing that in base class. Second we guaranteed this cast to work with where constraint and abstract.
Upvotes: 1
Reputation: 633
In your base class example, "this" is not a type of "T" but is instead a type of "baseClass{T}". That's why it doesn't work. I'm not sure what you're trying to accomplish here, but this would probably compile...
public class baseClass<T>
{
public baseClass<T> method1()
{
return this;
}
}
public class inheritedClass : baseClass<inheritedClass>
{
public baseClass<inheritedClass> method2()
{
return this.method1();
}
}
Edit: I understand your question now. This is probably a better overall approach than using inheritance. You can convert the interface to be a generic one if needed...
public interface FluentStuff
{
FluentStuff method1();
FluentStuff method2();
}
public class MyClass : FluentStuff
{
public FluentStuff method1()
{
return this;
}
public FluentStuff method2()
{
return this;
}
}
But if you insist on using inheritance...
public interface FluentStuff
{
FluentStuff method1();
FluentStuff method2();
}
public abstract class BaseClass : FluentStuff
{
public virtual FluentStuff method1()
{
return this;
}
public abstract FluentStuff method2();
}
public class MyClass : BaseClass, FluentStuff
{
public override FluentStuff method2()
{
return this;
}
}
I highly encourage composition over inheritance.
Example with generics...
public interface FluentStuff<T>
{
FluentStuff<T> method1();
FluentStuff<T> method2();
}
public abstract class BaseClass<T> : FluentStuff<T>
{
public virtual FluentStuff<T> method1()
{
return this;
}
public abstract FluentStuff<T> method2();
}
public class MyClass : BaseClass<MyClass>, FluentStuff<MyClass>
{
public override FluentStuff<MyClass> method2()
{
return this;
}
}
Final example to another question/concern you posted...
public class SharedFunctionality
{
public void DoStuff1()
{
// common implementation for do stuff 1
}
public void DoStuff2()
{
// common implementation for do stuff 2
}
}
public class MyClass1
{
private readonly SharedFunctionality sharedFunctionality;
public MyClass1()
{
this.sharedFunctionality = new SharedFunctionality();
}
public MyClass1 Method1()
{
this.sharedFunctionality.DoStuff1();
return this;
}
public MyClass1 Method2()
{
this.sharedFunctionality.DoStuff2();
return this;
}
}
public class MyClass2
{
private readonly SharedFunctionality sharedFunctionality;
public MyClass2()
{
this.sharedFunctionality = new SharedFunctionality();
}
public MyClass2 Method1()
{
this.sharedFunctionality.DoStuff1();
return this;
}
public MyClass2 Method2()
{
this.sharedFunctionality.DoStuff2();
return this;
}
public MyClass2 Method3()
{
// do something only this class does
return this;
}
}
class Program
{
static void Main(string[] args)
{
MyClass1 c1 = new MyClass1();
c1.Method1().Method2();
MyClass2 c2 = new MyClass2();
c2.Method1().Method2().Method3();
}
}
Upvotes: 1
Reputation: 127593
Your base class's return type should be the base class itself, not just T.
public class baseClass<T>
{
public baseClass<T> method1()
{
//Do stuffs
return this;
}
}
Upvotes: 1