C# interface implementation with derived interface - c#

In the following sample class "SomeClass" does not implement "ISomeInterface". Why can't I implement this by passing a more derived interface which does implement the base requirement. Whatever instance would be passed it would still implement the base, am I missing something?
namespace Test
{
public interface IBaseInterface
{
void DoBaseStuff();
}
public interface IChildInterface : IBaseInterface
{
void DoChildStuff();
}
public interface ISomeInterface
{
void DoSomething(IBaseInterface baseInterface);
}
public class SomeClass : ISomeInterface
{
public void DoSomething(IChildInterface baseInterface)
{
}
}
}

This restriction exists because the ISomeInterface expects that any IBaseInterface will satisfy the contract. That is, if you have the following:
public interface IBase {}
public interface IChildA : IBase {}
public interface IChildB : IBase {}
And an interface that expects IBase:
public interface IFoo { void Bar(IBase val); }
Then restricting this in a derived class as you would like:
public class Foo : IFoo { public void Bar(IChildA val) {} }
Would create the following problem:
IChildB something = new ChildB();
IFoo something = new Foo();
something.Bar(something); // This is an invalid call
As such, you're not implementing the contract you said you would.
In this situation, you have two simple options:
Adjust IFoo to be generic, and accept a T that is a derivation of IBase:
public interface IFoo<T> where T : IBase { void Bar(T val); }
public class Foo : IFoo<IChildA> { public void Bar(IChildA val) {} }
Of course, this means that Foo can no longer accept any IBase (including IChildB).
Adjust Foo to implement IFoo, with an additional utility method for void Bar(IChildA val):
public class Foo : IFoo
{
public void Bar(IBase val) {}
public void Bar(IChildA val) {}
}
This has an interesting side-effect: whenever you call ((IFoo)foo).Bar it will expect IBase, and when you call foo.Bar it will expect IChildA or IBase. This means it satisfies the contract, while also having your derived-interface-specific method. If you want to "hide" the Bar(IBase) method more, you could implement IFoo explicitly:
void IFoo.Bar(IBase val) { }
This creates even more inconsistent behavior in your code, as now ((IFoo)foo).Bar is completely different from foo.Bar, but I leave the decision up to you.
This means, with the second version in this section, that foo.Bar(new ChildB()); is now invalid, as IChildB is not an IChildA.
Why can't I implement this by passing a more derived interface which does implement the base requirement. Whatever instance would be passed it would still implement the base, am I missing something?
This is not allowed because of the reasoning I mentioned above, IFoo.Bar expects any IBase, whereas you want to further constrain the type to IChildA, which is not a super-interface of IBase, and even if it were it would not be allowed because it violates the interface implementation, though you could more easily define a second method at that point that does what you want.
Keep in mind that when you implement an interface, you subscribe to a contract, and C# will not let you violate that contract.

This violates the Liskov substitution principle.
ISomeInterface guarantees that the method can be called with any IBaseInterface instance. Your implementation cannot limit that to only accept IChildInterface interfaces.

From MSDN:
When a class or struct implements an interface, the class or struct must provide an implementation for all of the members that the interface defines
This method in the derived
void DoSomething(IChildInterface baseInterface)
Does not have the same signature as the one in the interface:
void DoSomething(IBaseInterface baseInterface)
IChildInterface and IBaseInterface are not the same types. Therefore your derived class does not implement all methods of the interface and you get the compilation error.
For a possible the logic behind having this as a restriction instead of the compiler understanding the inheritance see Liskov's substitution principle as in SLakes answer

You should change some interface to use some type which implements IBaseInterface,
then change the method signatures to use whichever child your SomeClass wants.
public interface ISomeInterface<TSomeChild> where TSomeChild : IBaseInterface
{
void DoSomething(TSomeChild baseInterface);
}
public class SomeClass : ISomeInterface<IChildInterface>
{
public void DoSomething(IChildInterface baseInterface)
{
}
}

If you could do that, then you could do this:
IAnimal cat = new Cat();
IAnimalTrainer dogTrainer = new DogTrainer();
dogTrainer.Train(cat);
An IAnimalTrainer can train any IAnimal. But a DogTrainer can only train Dogs. Thus it's illegal for DogTrainer to implement the IAnimalTrainer interface.

Related

Define protected abstract interface method as abstract in abstract class

I have an interface like this
interface IFoo
{
protected abstract int Compute();
int ComputeValue()
{
return Compute();
}
}
The idea being that Compute computes some value and ComputeValue maybe does some checks and then calls Compute to fetch the actual value. However, I now wonder how to implement this interface in an abstract class. I can do it like this
abstract class Bar : IFoo
{
public abstract int Compute();
}
but I dont want Compute to be called directly. However, when I try to implement it explicitly, e.g.
abstract class Bar : IFoo
{
abstract int IFoo.Compute();
}
I cannot define it as abstract in the abstract class Bar, which is what I want. Of course, I could do something like
abstract class Bar : IFoo
{
protected abstract int Compute();
int IFoo.Compute()
{
return Compute();
}
}
But I wonder is there a more elegant way of doing this without the additional extra method?
Not much you can do here. Though according toto the draft spec it was considered at some point to allow the support for explicit interface abstract overrides in classes (also see the reabstraction part):
Because we support explicit abstract overrides in interfaces, we could do so in classes as well
abstract class E : IA, IB, IC // ok
{
abstract void IA.M();
}
Open issue: should we support explicit interface abstract overrides in classes?
But it seems it was not followed through - see LDM-2019-03-27 Notes:
Explicit interface abstract overrides in classes
Allow abstract interface implementions in a class as well? Not an abstract class method implementing an interface method.
So either remove the Compute from the interface or use your current approach.

Base interface in c#

I need some sort of way to mark base interfaces and identify if a class implemented the base interface or its derived interface. c# doesn't allow having 'abstract interface'. Is there any way to do this in c#?
public interface IBaseFoo
{
void BaseMethod();
}
public interface IFoo : IBaseFoo
{
void FooMethod();
}
public class Base
{
}
public class A : Base, IFoo
{
}
public class B : Base, IBaseFoo
{
}
Now in the following method I need to check if the typeCls is implemented the IFoo or IBaseFoo without explicitly specifying types. I need sort of a way to mark the base interface and identify it in the method. (ie: if c# allowed having abstract interface, I could have check if IsAbstract property of interfaces of typeClas)
public bool IsBaseFooImplemented<T>(T typeCls) where T : Base
{
// Here I need to check if the typeCls is implemented the IFoo or IBaseFoo
}
Because IFoo : IBaseFoo, every class implementing IFoo also implements IBaseFoo. But not the other way around, so you can simply check whether typeCls is IFoo.
Do note that changing behavior based on implemented interfaces generally is a design smell that bypasses the use for interfaces in the first place.
//somewhere define
static List<IBaseFoo> list = new List<IBaseFoo>();
public class A : Base, IFoo
{
public A()
{
YourClass.list.add(this);
}
}
public class B : Base, IBaseFoo
{
public B()
{
YourClass.list.add(this);
}
}
//then you can check if a class is IFoo or not.
public bool IsBaseFooImplemented<T>(T typeCls) where T : Base
{
foreach(var c in list )
{
if(typeof(c) == typeCls) return true;
}
return false;
}
I have not tested the code but it should work.

Multiple inheritance with Abstract class and Interface

I have written the following code in C#.NET
public interface IWork
{
void func();
}
public abstract class WorkClass
{
public void func()
{
Console.WriteLine("Calling Abstract Class Function");
}
}
public class MyClass:WorkClass,IWork
{
}
On compiling, I didn't get any error. Compiler is not forcing me to implement the method "func();" in "MyClass", which has been derived from the interface "IWork".Latter, I can gracefully create a instance of the class "MyClass" and call the function "func()". Why the compiler is not forcing me to implement the "func()" method in the "MyClass"(which has been derived from "IWork" interface? Is it a flaw in C#?
While reading about this subject, I found I couldn't easily put it all together in my head, so I wrote the following piece of code, which acts as a cheat-sheet for how C# works. Hope it helps someone.
public interface IMyInterface
{
void FunctionA();
void FunctionB();
void FunctionC();
}
public abstract class MyAbstractClass : IMyInterface
{
public void FunctionA()
{
Console.WriteLine( "FunctionA() implemented in abstract class. Cannot be overridden in concrete class." );
}
public virtual void FunctionB()
{
Console.WriteLine( "FunctionB() implemented in abstract class. Can be overridden in concrete class." );
}
public abstract void FunctionC();
}
public class MyConcreteClass : MyAbstractClass, IMyInterface
{
public override void FunctionB()
{
base.FunctionB();
Console.WriteLine( "FunctionB() implemented in abstract class but optionally overridden in concrete class." );
}
public override void FunctionC()
{
Console.WriteLine( "FunctionC() must be implemented in concrete class because abstract class provides no implementation." );
}
}
class Program
{
static void Main( string[] args )
{
IMyInterface foo = new MyConcreteClass();
foo.FunctionA();
foo.FunctionB();
foo.FunctionC();
Console.ReadKey();
}
}
Gives the following output:
FunctionA() implemented in abstract class. Cannot be overridden in concrete class.
FunctionB() implemented in abstract class. Can be overridden in concrete class.
FunctionB() implemented in abstract class but optionally overridden in concrete class.
FunctionC() must be implemented in concrete class because abstract class provides no implementation.
To better understand the concept behind interfaces, I just give you the correct code of your implementation:
public interface IWork{
void func();
}
public abstract class WorkClass,IWork{
public void func(){
Console.WriteLine("Calling Abstract Class Function");
}
}
public class MyClass:WorkClass{
...
}
The basic rule: You need to include the interface always where the implementation is. So if you create a method within an abstract classes and define an interface of this method, you'll need to implement the interface into your abstract class and then all subclasses will automatically implement this interface.
As a matter of fact, interfaces have 2 kind of functions you can use them for:
1) As a "real" interface providing a generic handling of any class implementing the interface, so you can handle several kind of classes just by one interface (without knowing their real class names). While "handling" means: Calling a method.
2) As a help for other (framework) programmers not to mess up with your code. If you want to be sure that an method won't be replaced with another name, you define an interface for your class containing all "must have" method names. Even if the method is called nowhere, your programmer will get an compile error message when he changed the method name.
Now you can easily handle your Myclass just by the interface IWork.
Because the abstract class implements the interface.
If your class MyClass would not inherit from WorkClass you would get an error saying 'MyClass' does not implement interface member 'IWork.func()'.
But you also inherit from WorkClass, which actually implements the methods that the interface requires.
You can mark func() as abstract if you want to force the classes that inherits from it to implement it like this:
public abstract class WorkClass
{
public abstract void func();
}
I tried with the classes above in my solution.
It inherits the abstract class so the derived class have the func() method definition. This is the reason it was not able to show compiled errors.
func() is not marked as abstract in the WorkClass so you don't need to implement it in any classes that derive from WorkClass.
WorkClass implements the IWork interface so you don't need to implement it in MyClass because it inherits func() from WorkClass.
Since the func method in the abstract class is a non-virtual method, so the compiler thinks this method is a implementation of the interface.
When you extend MyClass to WorkClass, the method func() (which has been defined), is inherited.
So, when the interface IWork is implemented, the method 'func()' has already been defined. So, there are no more undefined methods in MyClass.
So, the class MyClass is a concrete class, due to which you are able to create a MyClass object without any compilation errors.

Abstract class does not implement interface

I have an interface so class writers are forced to implement certain methods. I also want to allow some default implemented methods, so I create a abstract class. The problem is that all classes inherit from the base class so I have some helper functions in there.
I tried to write : IClass in with the abstract base, but I got an error that the base didn't implement the interface. Well of course because I want this abstract and to have the users implement those methods. As a return object if I use base I can't call the interface class methods. If I use the interface I can't access base methods.
How do I make it so I can have these helper classes and force users to implement certain methods?
Make sure methods in the base class have the same name as the interface, and they are public. Also, make them virtual so that subclasses can override them without hiding them.
interface IInterface {
void Do();
void Go();
}
abstract class ClassBase : IInterface {
public virtual void Do() {
// Default behaviour
}
public abstract void Go(); // No default behaviour
}
class ConcreteClass : ClassBase {
public override void Do() {
// Specialised behaviour
}
public override void Go() {
// ...
}
}
Move the interface methods into the abstract class and declare them abstract as well. By this, deriving classes are forced to implement them. If you want default behaviour, use abstract classes, if you want to only have the signature fixed, use an interface. Both concepts don't mix.
Having faced with the same problem recently, I've came up with a somewhat more elegant (to my mind) solution. It looks like:
public interface IInterface
{
void CommonMethod();
void SpecificMethod();
}
public abstract class CommonImpl
{
public void CommonMethod() // note: it isn't even virtual here!
{
Console.WriteLine("CommonImpl.CommonMethod()");
}
}
public class Concrete : CommonImpl, IInterface
{
void SpecificMethod()
{
Console.WriteLine("Concrete.SpecificMethod()");
}
}
Now, according to C# spec (13.4.4. Interface mapping), in the process of mapping IInterface on Concrete class, compiler will look up for CommonMethod in CommonImpl too, and it doesn't even have to be virtual in the base class!
The other significant advantage, compared to Mau's solution, is that you don't have to list every interface member in the abstract base class.

Need help understanding abstract classes that implement an interface

Consider the following example. I have an interface MyInterface, and then two abstract classes MyAbstractClass1 and MyAbstractClass2. MyAbstractClass1 implements MyInterface, but MyAbstractClass2 does not.
Now I have three concrete classes.
MyConcreteClass1 is derived from MyAbstractClass1 but does not implement MyInterface.
MyConcreteClass2 is derived from MyAbstractClass2, but does implement MyInterface.
MyConcreteClass3 is derived from MyAbstractClass1, and does implement MyInterface.
Does ConcreteClass1 also implicitly implement MyInterface because it derives from MyAbstractClass1? Assuming MyAbstractClass1 implements the methods of MyInteface implicitly then ConcreteClass1 should not have to be cast to a MyInterface to access the MyInteface methods right?
MyAbstractClass1 can implicitly implement a method of MyInterface as an abstract method, but can't explicitly implement a method of MyInterface as an abstract method. Why is this?
Is MyConcreteClass3 excessive because it's implementing an interface that is already implemented by its base class? Would there be a reason you would want to do that even if you knew all classes that derive from MyAbstractClass1 should also implement MyInterface.
Here's a class diagram
alt text http://files.getdropbox.com/u/113068/abstractclassesandinterfaces.png
Here's the code:
//interface
public interface MyInterface
{
void MyMethodA();
void MyMethodB();
void MyMethodC();
}
//abstract classes
public abstract class MyAbstractClass1 : MyInterface
{
public void MyMethodA()
{
}
void MyInterface.MyMethodB()
{
}
//Error: "the modifier abstract is not valid for this item"
//abstract void MyInterface.MyMethodC();
//This works
public abstract void MyMethodC();
public abstract void MyMethodZ();
}
public abstract class MyAbstractClass2
{
public void MyMethodX()
{
}
public abstract void MyMethodY();
}
//Concrete classes
//ConcreteClass 1: Only Abstract class implements the interface
public class ConcreteClass1 : MyAbstractClass1
{
public override void MyMethodC()
{
}
public override void MyMethodZ()
{
}
}
//ConcreteClass 1: Only Concrete class implements the interface
public class ConcreteClass2 : MyAbstractClass2, MyInterface
{
public override void MyMethodY()
{
}
public void MyMethodA()
{
}
public void MyMethodB()
{
}
public void MyMethodC()
{
}
}
//ConcreteClass 1: Both concrete and abstract class implement the interface
public class ConcreteClass3 : MyAbstractClass1, MyInterface
{
public override void MyMethodC()
{
}
public override void MyMethodZ()
{
}
}
Does ConcreteClass1 also implicitly implement MyInterface because it derives from MyAbstractClass1?
Yes.
ConcreteClass1 should not have to be cast to a MyInterface to access the MyInteface methods right?
Correct. (myConcreteClass1 is MyInterface) will evaluate true.
MyAbstractClass1 can implicitly implement a method of MyInterface as an abstract method, but can't explicitly implement a method of MyInterface as an abstract method.
Explicit implementation is to distinguish between overlapping member signatures. The explicit implementation is private to the class you are implementing it on, so it is not accessible to derived classes (and thus cannot be abstract). You also cannot force classes which derive from MyAbstractClass1 to explicitly implement MyInterface, so there is no way to ensure the abstract member will ever be implemented.
Is MyConcreteClass3 excessive because it's implementing an interface that is already implemented by its base class? Would there be a reason you would want to do that even if you knew all classes that derive from MyAbstractClass1 should also implement MyInterface.
Not necessarily, If you need to explicitly implement a member of the interface to distinguish it from an overlapping member on MyConcreteClass3. Otherwise it is unnecessary.
In this case, all three classes implement the interface (directly or indirectly). This is because MyAbstractClass1 implements MyInterface, and since MyConcreteClass1 derives from MyAbstractClass1, it also follows that you can treat MyConcreteClass1 as a MyInterface. MyConcreteClass2 can be treated with something that derives from MyAbstractClass1, as long as you treat it as a MyInterface. the derivation from MyInterface in ConcreteClass3 is a bit redundant since MyAbstractClass1 already implements MyInterface.
With all of that information, i'd say that yes, it is redundant to implement MyInterface on MyConcreteClass3 since it derives from MyAbstractClass1 which already implements MyInterface.
I think the reason that you cant have an abstract implementation of an interface method is that it provides no code itself and you cannot guarantee that it will be overriden in subcalsses. Use Virtual instead.
It's not redundant. Consider this class setup to simplify ...
public interface I
{
void A();
}
public abstract class B : I
{
public void A( )
{
Console.WriteLine("Base");
}
}
public class D : B
{
public void A()
{
Console.WriteLine("Hide");
}
}
public class U
{
public void M(I i)
{
Console.WriteLine("M!");
}
}
Executing this ...
var d = new D();
var i = (I)d;
var u = new U();
i.A();
d.A();
u.M(d);
u.M(i);
You will get ...
Base
Hide
M!
M!
If you add the interface from the derived class ...
public class D : B, I
{
public void A()
{
Console.WriteLine("Hide");
}
}
You will get ...
Hide
Hide
M!
M!
So, it effects which implementation of the interface method you get when you get the Iness of your derived class.

Categories

Resources