Подтвердить что ты не робот

Реализация метода переопределения, объявленного в интерфейсе

У меня есть интерфейс с несколькими методами.

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

И реализация

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

Теперь я хочу иметь класс, который ведет себя как MyClass, кроме OnItemClicked(), мне нужны некоторые модификации для этого метода.

Я думал, что наследует переопределение, но я не хочу изменять MyClass (например: public virtual void OnItemClicked()...), потому что его не моя реализация,

Я не хочу реализовывать IMyInterface снова, потому что OnItemClicked() является единственной частью MyClass для изменения.

Есть ли у меня другой способ сделать это?

4b9b3361

Ответ 1

Поскольку вы реализуете интерфейс, полиморфизм, вероятно, вы хотите сохранить. Невозможно переопределить метод, не модифицируя базовый класс виртуальным, поэтому вы должны использовать новый вместо виртуального, как писал Тигран.

Это означает, что для написания этого типа кода будет выполняться только базовая версия метода:

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

Чтобы выполнить правильный код, вы должны написать уродливый код следующим образом:

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();
}

Во всяком случае, есть способ, чтобы ваши классы выполняли правильный метод, когда они назначены переменным, объявленным как IMyInterface. Путь к тому, чтобы явно реализовать часть интерфейса, которую вы хотите переопределить, в вашем случае метод OnItemClicked. Код следующий:

public class MyNewClass : MyClass, IMyInterface // you MUST explicitly say that your class implements the interface, even if it 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 methods must be public)
    { 
        this.OnItemClicked(); 
    } 
}

Таким образом:

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

выполняет базовый метод

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

выполняет метод производного класса

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

выполняет метод производного класса и привязан во время выполнения. Это означает, что вы можете написать код моего первоначального примера, как это, и выполнить правильные методы:

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

Ответ 2

вы можете получить из MyClass

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

Единственное, обратите внимание, что таким образом вы не supprot полиморфизм.

Чтобы быть более ясным:

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

это вызовет метод MyClass, даже если тип реального объекта MyNewType. Чтобы иметь возможность вызывать то, что мы хотим, мы должны определить тип

     MyNewClass cl = new MyNewClass(); 
     cl. MyMethod(); //WILL CALL METHOD WE WANT

Ответ 3

Самый простой способ - создать новый класс, который имитирует "is-a", используя "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();
    }
}