I am encountering a problem with interfaces. I wish to chain a method which derives its chainable method from an abstract class, which implements an interface.
public interface IBaseInterface {
public IBaseInterface ChainableMethod()
}
public abstract AbstractClassThatHelps<T> where T: IBaseInterface n {
public T ChainableMethod() {
return (T) this;
}
}
public interface IDerived : IBaseInterface { }
public class DerivedClass : AbstractClassThatHelps<IDerived>, IDerived { }
IDerived derived = new DerivedClass();
derived.ChainableMethod().ChainableMethod();
The problem I face here: why can't T be returned when it is shown to implement the contract IModel?
How would I solve this differently? I wish to have type safety but I am forced for all derived classes to return IBaseInterface instead of their own interface.
Actual implementation:
We have multiple models (DerivedClass's) which implement their respective IDerived for dependency injection. These need helpers because i dont want to repeat myself.. So we use AbstractClassThatHelps as a base, but because we are dealing with chainable methods we need this base class to know what to return, so therefore generics. IBaseInterface can be seen as IModel. Where ChainableMethod can be seen as GetAll() for example.
In order for the following code to work AbstractClassThatHelps<T> must implement IBaseInterface. How can you return this, if this is not IBaseInterface
public abstract AbstractClassThatHelps<T> where T: IBaseInterface n{
public T ChainableMethod(){
return this;
}
}
Edit: I am not user what this design solves but here is my attempt at what you are trying to achieve→
public interface IBaseInterface
{
IBaseInterface ChainableMethod();
}
public abstract class AbstractClassThatHelps<T>:IBaseInterface where T : IBaseInterface{
public T ChainableMethod()
{
IBaseInterface i = this;
return (T)i.ChainableMethod();
}
IBaseInterface IBaseInterface.ChainableMethod()
{
return this;
}
}
public class Concrete : AbstractClassThatHelps<Concrete>
{
}
You can return an instance of T, but the return type cannot be T but must be IBaseInterface because that is what the interface requires.
This is working, your code was full of syntax errors:
public interface IBaseInterface
{
IBaseInterface ChainableMethod();
}
public abstract class AbstractClassThatHelps : IBaseInterface
{
public IBaseInterface ChainableMethod()
{
return this;
}
}
public interface IDerived : IBaseInterface
{
}
public class DerivedClass : AbstractClassThatHelps, IDerived
{
}
internal static class Program
{
public static void Main()
{
IDerived derived = new DerivedClass();
derived.ChainableMethod().ChainableMethod();
}
}
you could also try this:
public interface IBaseInterface
{
IBaseInterface ChainableMethod();
}
public abstract class AbstractClassThatHelps<T> : IBaseInterface where T : class, IBaseInterface
{
public T ChainableMethod()
{
return this as T;
}
IBaseInterface IBaseInterface.ChainableMethod()
{
return ChainableMethod();
}
}
public interface IDerived : IBaseInterface
{
IDerived Hello();
}
public class DerivedClass : AbstractClassThatHelps<IDerived>, IDerived
{
public IDerived Hello()
{
Console.WriteLine("Hello");
return this;
}
}
internal static class Program
{
public static void Main()
{
AbstractClassThatHelps<IDerived> derived = new DerivedClass();
derived.ChainableMethod().Hello().ChainableMethod();
}
}
Related
Suppose a class defined as below,
public class MyGeneric<T> where T : MyGeneric<T>
{
}
Can we create an object of this class? If not, why does this exist?
I'm asking this of my curiosity and don't have an in depth knowledge in C#.
It's useful when you have a class hierarchy, and you want to be able to write methods in the base class which return instances of the derived class (such as this):
public abstract class Base<T> where T : Base<T>
{
public T WithFoo(int foo)
{
// ...
return (T)this;
}
}
public class Derived : Base<Derived>
{
// ...
}
Derived d = new Derived().WithFoo(3);
Of course, this doesn't stop someone from writing:
public class Other : Base<Derived> { }
... and the only way to get around this is with a runtime check, which can be ugly:
public Base()
{
Trace.Assert(typeof(T) == this.GetType());
}
Some other languages have specific keywords to cover this case.
You can do it by inheriting from MyGeneric:
public class MyGeneric<T> where T : MyGeneric<T>
{
}
class MyGenericChild : MyGeneric<MyGenericChild>
{
}
var myGenericChild = new MyGenericChild();
var myGeneric = new MyGeneric<MyGenericChild>();
This is helpful when there is need to create type-specific members in the base class, specific to the actual descendant.
public class MyGeneric<T> where T : MyGeneric<T>
{
public void Do(T t)
{
...
}
}
class MyGenericChild : MyGeneric<MyGenericChild>
{
// Do for MyGenericChild will accept only MyGenericChild and it's descendants
}
My project is structured the following way:
// Abstract class
public abstract class Job
{
public abstract JobResult Run();
}
public abstract class JobResult { }
// Concrete implementer
public class Job1 : Job
{
public override Job1Result Run() { }
}
public class Job1Result : JobResult { }
Each concrete job inherits from Job and implements the method Run which returns a concrete class of JobResult.
However when I do this I get the compiler error:
Job1.Run()': return type must be JobResult to match overridden member
Job.Run()
Is it really not possible to return an inheriting object of the return type when overriding an abstract method?
This is the whole concept of inheritance. Returning parent classes is considered a feature here. Nothing stops you however from returning a Job1Result in Job1
public JobResult Run()
{
return new Job1Result();
}
Then the caller of Job1.Run() will have to know the correct return type and cast it to access Job1Result methods which are specific to that class
You could make Job generic:
public abstract class Job<TResult> where TResult : JobResult
{
public abstract TResult Run();
}
public class Job1 : Job<Job1Result>
{
public override Job1Result Run()
{
//
}
}
Here is an example, I hope it can help you.
public interface IEvent
{
Type GetEventType();
}
public abstract class AEvent<A>: IEvent where A: struct
{
public Type GetEventType()
{
return typeof (A); // return sub struct type
}
}
I'm trying to implement the best code re-usability. The problem is that I can't access the base method located in the Base Abstract class form the Main Program through the repository.
If you go through the example below you will see a sample code of my situation.
So my question is how can I access methods located in the base abstract class from the main program.
Classes/Interfaces
public abstract class BaseEntity
{
public override abstract String ToString();
}
public abstract class BaseClass<T> where T : BaseEntity
{
public T GetById(int id)
{
//Dummy Code
return new T();
//
}
}
public interface IFooRepository
{
IList<Foo> GetOrderedObjects();
}
public interface FooRepository : BaseClass<Foo>, IFooRepository
{
public IList<Foo> GetOrderedObjects()
{
//GetById method is accessible from the repository - Fine
var obj = this.GetById(5);
//Dummy Code
return new List<Foo>();
//
}
}
//Main App
public class void Main()
{
private IFooRepository _fooRepository;
public void ProgramStartsHere()
{
//This is ok.
var list = _fooRepository.GetOrderedObjects();
//Problem is here - GetById method is not accessible from the main program through the FooRepository
var obj = _fooRepository.GetById(10);
}
}
GetById isn't defined in the interface
I would make an
public interface IBaseRepository<T> where T : BaseEntitiy {
T GetById<T>(int id);
}
Then BaseClass implements IBaseRepository<T>
and IFooRepository inherits from IBaseRepository<Foo>
EDIT :
A full example, similar to #Olivier J-D one, with idea (maybe wrong), that GetOrderedObject may be same for all your entities.
public abstract class BaseEntity
{
public override abstract String ToString();
}
//all generic methods
public interface IRepositoryBase<T>
where T : BaseEntity, new()
{
T GetById(int id);
IList<T> GetOrderedObjects();
}
//all methods specific to foo, which can't be in a generic class
public interface IFooRepository :IRepositoryBase<Foo>
{
void Update(Foo model);
}
//implementation of generic methods
public abstract class BaseClass<T> : IRepositoryBase<T>
where T : BaseEntity, new() // ===> Add new() constraint here
{
public T GetById(int id)
{
return new T();
}
public IList<T> GetOrderedObjects() {
var obj = this.GetById(5);
//Dummy Code
return new List<Foo>();
//
}
}
//implementation of Foo specific methods
public class FooRepository : BaseClass<Foo>, IFooRepository
{
public void Update(Foo model) {
//bla bla
}
}
Add a new Interface which declares the GetById method and let IFooRepository and BaseClass<T> inherit from it. You will have to add a generic type parameter to IFooRepository as well. (I renamed IFooRepository to IRepository<T>, since it is generic now.)
public abstract class BaseEntity
{
public override abstract String ToString();
}
public interface IRetriever<T>
where T : BaseEntity, new()
{
T GetById(int id);
}
public interface IRepository<T> : IRetriever<T>
where T : BaseEntity, new()
{
IList<T> GetOrderedObjects();
}
public abstract class BaseClass<T> : IRetriever<T>
where T : BaseEntity, new() // ===> Add new() constraint here
{
public T GetById(int id)
{
return new T();
}
}
public class FooRepository : BaseClass<Foo>, IRepository<Foo>
{
public IList<Foo> GetOrderedObjects()
{
var obj = this.GetById(5);
return new List<Foo>();
}
}
This will work fine then
IRepository<Foo> _fooRepository = new FooRepository();
var list = _fooRepository.GetOrderedObjects();
var obj = _fooRepository.GetById(10);
Your _fooRepository inherits from IFooRepository, not FooRepository, so it doesn't have access to GetById(10);
You must expose the GetById method in your repository interface.
public interface IFooRepository
{
IList<Foo> GetOrderedObjects();
Foo GetById(int id);
}
Alternatively you can use a type parameter constraint, as stated by Raphaël Althaus
IFooRepository doesn't inherit from BaseClass, so you have to cast _fooRepository to FooRepository. Then you can access GetById()
Cast it to the base class.
var obj = ((BaseClass<Foo>)_fooRepository).GetById(10);
I'm a .NET developer and know pretty much about OOP.
However, recently I noticed one interesting fact.
System.Data.SqlClient.SqlCommand derives from
System.Data.Common.DbCommand. The latter implements System.IDbCommand.
System.IDbCommand exposes the property Connection which an instance of IDbConnection.
In DbCommand However this property returns DbConnection type. And finally the same property in SqlCommand is of type SqlConnection
I've tried to perform the same however it gave a compile time error. How was this achieved in above example and how can I recreate the same pattern?
My code (not compiling):
public interface IFoo { }
public interface IBar
{
IFoo TheFoo();
}
public abstract class AbsFoo : IFoo { }
public abstract class AbsBar : IBar
{
public abstract AbsFoo TheFoo();
}
public class ConcreteFoo : AbsFoo { }
public class ConcreteBar : AbsBar { }
Explicit interface implementation is the name of the game here. Try this:
public abstract class AbsBar : IBar {
IFoo IFoo.TheFoo() { return this.TheFoo(); }
public abstract AbsFoo TheFoo();
}
Here's a good guide on implicit vs. explicit implementation.
I have to say that I think Richard was a little hard done by - his answer is just as good as Jason's in that they both only answered half of the question. Put them both together and you have the full answer.
To make this work with IDbCommand, DbCommand & SqlCommand there has to be an explicit implementation of IDbCommand in DbCommand (Jason's answer) and public method shadowing in SqlCommand (Richard's answer).
I'll give the full "Foo/Bar" example.
Start with these interfaces:
public interface IFoo
{
IBar GetBar();
}
public interface IBar { }
Next Foo must provide an explicit implementation of IFoo in order to return Bar, not IBar, from its own GetBar method:
public abstract class Foo : IFoo
{
IBar IFoo.GetBar()
{
return this.GetBar();
}
public Bar GetBar()
{
return this.GetBarInner();
}
protected abstract Bar GetBarInner();
}
public abstract class Bar : IBar { }
And finally a SomeFoo class must shadow GetBar to be able to return a SomeFoo instance:
public class SomeFoo : Foo
{
public new SomeBar GetBar()
{
return new SomeBar();
}
protected override Bar GetBarInner()
{
return this.GetBar();
}
}
public class SomeBar : Bar { }
I think the only information that Richard is that my adding the new keyword to the shadowed method you get rid of the compiler error.
Connection in DbCommand and SqlCommand are both just public methods. There would be a compiler warning, but it's allowed. Your code should be more like this to work like SqlCommand/DbCommand:
public interface IFoo { }
public abstract class AbsBaseBar
{
public IFoo TheFoo() { throw new NotImplementedException(); }
}
public class AbsFoo : IFoo { }
public class AbsBar : AbsBaseBar
{
public AbsFoo TheFoo() { throw new NotImplementedException(); }
}
public class ConcreteFoo : AbsFoo { }
public class ConcreteBar : AbsBar { }
I trying to inherit a class Blah2, but after adding a method it says BlahA doesn't implement that method.
How can I add a method to my new class?
public class Blah2 : BlahA
{
}
public class Blah3 : Blah2
{
public List<int> MyNewMethod()
{
}
}
Note: BlahA is an abstract class.
Update
public abstract class BlahA : IBlah
{
}
Update II - the error
Error 3 'Blah.Components.BlahA' does not contain a definition for 'Blah3' and no extension method 'Blah3' accepting a first argument of type 'Blah.Components.BlahA' could be found (are you missing a using directive or an assembly reference?)
Well if it's implementing an interface as you posted in your comments, then the problem is that your BlahA class doesn't satisfy the requirements of the interface. There must be some method in the interface (I'm assuming its the MyNewMethod) that you're not implementing in your abstract BlahA class.
If my assumption is correct, add this to your base class:
public abstract List<int> MyNewMethod();
and in your sub class, add the word override to your method declaration.
Some code:
public interface MyInterface
{
void MyMethod();
}
public abstract class Base : MyInterface
{
public abstract void MyMethod();
}
public class SubA : Base
{
public override void MyMethod()
{
throw new NotImplementedException();
}
}
public class SubB : SubA
{
public void Foo() { }
}
Wrting this code and compiling works fine
public abstract class BlahA
{
}
public class Blah2 : BlahA
{
}
public class Blah3 : Blah2
{
public List<int> MyList()
{
return new List<int>();
}
}
We will need a bit more of the code that isnt working
EDIT:
from comments you need to implement the method from interface in abstract class.
public interface IBlah
{
int GetVal();
}
public abstract class BlahA : IBlah
{
public int GetVal()
{
return 1;
}
}
public class Blah2 : BlahA
{
}
public class Blah3 : Blah2
{
public List<int> MyList()
{
int i = GetVal();
return new List<int>();
}
}