Suppose if I have an Interface as defined below:
public interface IFunctionality
{
void Method();
}
and I implement this interface for an abstract class as shown below:
public abstract class AbstractFunctionality: IFunctionality
{
public void Method()
{
Console.WriteLine("Abstract stuff" + "\n");
}
}
again I have a concrete class which Inherits from abstract class as below:
public class ConcreteFunctionality: AbstractFunctionality
{
public void Method()
{
Console.WriteLine("Concrete stuff" + "\n");
}
}
Now I have the following code,
ConcreteFunctionality mostDerived = new ConcreteFunctionality();
AbstractFunctionality baseInst = mostDerived;
IFunctionality interfaceInst = mostDerived;
mostDerived.Method();
baseInst.Method();
interfaceInst.Method();
The output which I am getting after execution of this stuff is as following.
Concrete stuff
Abstract stuff
Abstract stuff
But what I have been expecting the output to be "Concrete Stuff" in all the three cases as what I am doing here is assigning the reference of ConcreteFunctionality
to the variables of type AbstractFunctionality
and IFunctionality
.
What is happening internally. Kindly clarify.
Here:
public class ConreteFunctionality:AbstractFunctionality
{
public void Method()
{
Console.WriteLine("Concrete stuff" + "\n");
}
}
... you're not overriding the existing method. You're creating a new method which hides the existing one. (You should get a warning, too, suggesting the use of the new
modifier if you really want this behaviour.) The interface was implemented in AbstractFunctionality
, so the interface mapping table refers to the method in that class.
Now if you reimplement the interface:
public class ConcreteFunctionality : AbstractFunctionality, IFunctionality
... then the interface mapping will refer to the method in ConcreteFunctionality
and you'll get the behaviour you expect for the call through the interface (i.e. your third call) but you'd still get the implementation in AbstractFunctionality
for your second call.
It would be generally cleaner and more sanity-preserving to make the method in AbstractFunctionality
virtual, and override it in ConcreteFunctionality
. That way it will use the ConcreteFunctionality
implementation in all cases.