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

Наследование интерфейса С# для абстрактного класса

Предположим, что у меня есть интерфейс, как определено ниже:

public interface IFunctionality
{
    void Method();       
}

и я реализую этот интерфейс для абстрактного класса, как показано ниже:

public abstract class AbstractFunctionality: IFunctionality
{
    public void Method()
    {
        Console.WriteLine("Abstract stuff" + "\n");
    }       
}

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

public class ConcreteFunctionality: AbstractFunctionality
{
    public void Method()
    {
        Console.WriteLine("Concrete stuff" + "\n");
    }
}

Теперь у меня есть следующий код,

ConcreteFunctionality mostDerived = new ConcreteFunctionality();
AbstractFunctionality baseInst = mostDerived;
IFunctionality interfaceInst = mostDerived;
mostDerived.Method();
baseInst.Method();
interfaceInst.Method();

Результат, который я получаю после выполнения этого материала, выглядит следующим образом.

Concrete stuff
Abstract stuff
Abstract stuff

Но то, что я ожидал, что вывод будет "Concrete Stuff" во всех трех случаях, поскольку то, что я здесь делаю, присваивает ссылку ConcreteFunctionality переменным типа AbstractFunctionality и IFunctionality.

Что происходит внутри страны. Просьба уточнить.

4b9b3361

Ответ 1

Здесь:

public class ConreteFunctionality:AbstractFunctionality
{
    public void Method()
    {
        Console.WriteLine("Concrete stuff" + "\n");
    }
}

... вы не переопределяете существующий метод. Вы создаете новый метод, который скрывает существующий. (Вы также должны получить предупреждение, предлагающее использовать модификатор new, если вы действительно этого хотите.) Интерфейс был реализован в AbstractFunctionality, поэтому таблица сопоставления интерфейса ссылается на метод в этом классе.

Теперь, если вы переопределите интерфейс:

public class ConcreteFunctionality : AbstractFunctionality, IFunctionality

... тогда сопоставление интерфейса будет ссылаться на метод в ConcreteFunctionality, и вы получите поведение, которое вы ожидаете для вызова через интерфейс (т.е. ваш третий вызов), но вы все равно получите реализацию в AbstractFunctionality для вашего второго вызова.

Было бы более чистым и более безопасным, чтобы сделать метод в AbstractFunctionality виртуальным и переопределить его в ConcreteFunctionality. Таким образом, он будет использовать реализацию ConcreteFunctionality во всех случаях.

Ответ 2

Вам нужно определить классы как:

public abstract class AbstractFunctionality:IFunctionality
{
    public virtual void Method()
    {
        Console.WriteLine("Abstract stuff" + "\n");
    }       
}

public class ConreteFunctionality:AbstractFunctionality
{
    public override void Method()
    {
        Console.WriteLine("Concrete stuff" + "\n");
    }
}

Поскольку вы не переопределили метод() в ConreteFunctionality, среда времени выполнения выполняет метод(), связанный с объектом AbstractFunctionality, поскольку здесь он не может применять динамический полиморфизм. Введение virtual и override заставляет среду выполнения выполнять метод переопределения в дочернем классе.

Ответ 3

Вам не хватает ключевых слов virtual и override. Без этого вы не получите виртуальных функций.

Вы можете пометить Method в AbstractFunctionality как virtual и пометить Method в ConreteFunctionality как override. Как показал михир.

Аналогичные проблемы решаются в Почему методы интерфейса С# не объявлены абстрактными или виртуальными?