Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override method implementation declared in an interface

I've got an interface with a several methods in it.

interface IMyInterface
{
    //...
    void OnItemClicked()
    //...
}

And an implementation

class MyClass : IMyInterface
{
    //Other methods
    public void OnItemClicked(){ /*...*/ } 
}

Now, I want to have a class that behaves like MyClass except of OnItemClicked(), I want some modifications for this method.

I thought to inherit an override but I don't want to change the MyClass (like: public virtual void OnItemClicked()...) because its not my implementation,

I don't want to implement IMyInterface again because the OnItemClicked() is the only part of MyClass to modify.

Do I have any other way to do it?

like image 644
Miklós Balogh Avatar asked Sep 07 '12 09:09

Miklós Balogh


4 Answers

Since you are implementing an interface, polymorphism is probably something you'd like to keep. It's impossible to override the method without modyfing the base class with a virtual, so you must use new instead of virtual as Tigran wrote.

This means that writing this kind of code but only the base version of the method would be executed:

List<MyClass> aList = new List<MyClass>();
aList.Add(new MyClass());
aList.Add(new MyNewClass());
foreach (MyClass anItem in aList)
    anItem.OnItemClicked();

To execute the right code you should write ugly code like this:

List<MyClass> aList = new List<MyClass>();
aList.Add(new MyClass());
aList.Add(new MyNewClass());
foreach (MyClass anItem in aList)
{
    MyNewClass castItem = anItem as MyNewClass;
    if (castItem != null)
        castItem.OnItemClicked();
    else
        anItem.OnItemClicked();
}

Anyway there is a way to have your classes executing the right method when they are assigned to variables declared as IMyInterface. The way to go is to explicitly implement the part of the interface that you want to override, in your case the OnItemClicked method. The code is the following:

public class MyNewClass : MyClass, IMyInterface // you MUST explicitly say that your class implements the interface, even if it's derived from MyClass
{
    public new void OnItemClicked() //NEW keyword here you have the overridden stuff
    { 
        /*...*/ 
    } 

    void IMyInterface.OnItemClicked() // No need for public here (all interfaces's methods must be public)
    { 
        this.OnItemClicked(); 
    } 
}

In this way:

 MyClass cl = new MyNewClass(); 
 cl.OnItemClicked();

executes the base method

 MyNewClass cl = new MyNewClass(); 
 cl.OnItemClicked();

executes the method of the derived class

 IMyInterface cl = new MyNewClass(); 
 cl.OnItemClicked();

executes the method of the derived class and is bound at runtime. This means that you can write the code of my initial example like this and have the right methods executed:

List<IMyInterface> aList = new List<IMyInterface>();
aList.Add(new MyClass());
aList.Add(new MyNewClass());
foreach (IMyInterface anItem in aList)
    anItem.OnItemClicked();
like image 53
Francesco Baruchelli Avatar answered Nov 17 '22 10:11

Francesco Baruchelli


you can derive from MyClass

public class MyNewClass : MyClass
{
    public new void OnItemClicked(){ /*...*/ } //NEW keyword
}

The only thing, pay attention that in this way you do not supprot polymorphism.

To be more clear:

     MyClass cl = new MyNewClass(); 
     cl. MyMethod();

this will call MyClass method, even if the real object type is MyNewType. To be able to call what we want, we have to esplicitly define type

     MyNewClass cl = new MyNewClass(); 
     cl. MyMethod(); //WILL CALL METHOD WE WANT
like image 42
Tigran Avatar answered Nov 17 '22 09:11

Tigran


The easiest way is to create a new class that mimics "is-a" using "has-a":

public interface IMyInterface
{
    void OnItemClicked();
    void OnItemHover();
    void OnItemDoubleClicked();
}

public class MyNewClass : IMyInterface
{
    private IMyInterface _target;

    public MyNewClass(IMyInterface target)
    {
        _target = target;
    }

    public void OnItemClicked()
    {
        // custom functionality
    }

    public void OnItemHover()
    {
        _target.OnItemHover();
    }

    public void OnItemDoubleClicked()
    {
        _target.OnItemDoubleClicked();
    }
}
like image 3
armen.shimoon Avatar answered Nov 17 '22 10:11

armen.shimoon


use pattern bridge http://en.wikipedia.org/wiki/Bridge_pattern

like image 1
burning_LEGION Avatar answered Nov 17 '22 09:11

burning_LEGION