Каковы реальные примеры абстрактных новых / виртуальных / переопределенных / абстрактных ключевых слов?

2

Я перехожу от PHP к С#.

В PHP было просто и просто использовать абстрактные классы для создания шаблона каскадного переопределения, в основном " метод базового класса позаботится об этом, если класс наследования не имеет метод с той же сигнатурой".

В С#, однако, я потратил около 20 минут на различные комбинации ключевых слов Новый, виртуальный, абстрактный и переопределить в базовом и наследовании, пока я наконец не получу правильную комбинацию, которая делает этот простой каскадный шаблон переопределения.

Итак, даже те, что ниже кода работают так, как я хочу, эти добавленные ключевые слова подсказывают мне, что С# может делать гораздо больше с абстрактными классами. Я искал примеры этих ключевых слов и в основном понимаю, что они делают, но до сих пор не может представить себе реального сценария, в котором я бы использовал их, кроме этого простого шаблона "каскадного переопределения". Каковы некоторые реальные способы реализации этих ключевых слов в вашем ежедневном программировании?

который работает:

using System;

namespace TestOverride23433
{
    public class Program
    {
        static void Main(string[] args)
        {
            string[] dataTypeIdCodes = { "line", "wn" };
            for (int index = 0; index < dataTypeIdCodes.Length; index++)
            {
                DataType dataType = DataType.Create(dataTypeIdCodes[index]);
                Console.WriteLine(dataType.GetBuildItemBlock());
            }

            Console.ReadLine();
        }
    }

    public abstract class DataType
    {
        public static DataType Create(string dataTypeIdCode)
        {
            switch (dataTypeIdCode)
            {
                case "line":
                    return new DataTypeLine();
                case "wn":
                    return new DataTypeWholeNumber();
                default:
                    return null;
            }
        }

        //must be defined as virtual
        public virtual string GetBuildItemBlock()
        {
            return "GetBuildItemBlock executed in the default datatype class";
        }
    }

    public class DataTypeLine : DataType
    {
        public DataTypeLine()
        {
            Console.WriteLine("DataTypeLine just created.");
        }
    }

    public class DataTypeWholeNumber : DataType
    {
        public DataTypeWholeNumber()
        {
            Console.WriteLine("DataTypeWholeNumber just created.");
        }

        //new public override string GetBuildItemBlock()  //base method is erroneously executed
        //public override string GetBuildItemBlock() //gets error "cannot override inherited member because it is not marked virtual, abstract, or override"
        public override string GetBuildItemBlock()
        {
            return "GetBuildItemBlock executed in the WHOLENUMBER class.";
        }
    }

}
  • 0
    Вот некоторые заметки о (редких) ситуациях, когда можно использовать «new» для скрытия методов. blogs.msdn.com/ericlippert/archive/2008/05/21/...
Теги:
abstract-class

3 ответа

8
Лучший ответ

virtual/override - пара основных полиморфизмов; похоже, что вы уже взломали эти

abstract похож на virtual, но там нет разумной базовой реализации; прецеденты: возможно, Stream, где необходимо для фактической реализации сделать что-то с байтами. Это заставляет класс abstract

new следует избегать; он ломает полиморфизм... наиболее распространенным случаем является повторное выставление с более конкретным сигналом/возвращаемым типом (возможно, в запечатанном классе, поскольку он не красивее цепочки...) - см. SqlConnection.CreateCommand (vs DbConnection.CreateCommand) или (возможно, более заметно ) IEnumerator<T>.Current (vs IEnumerator.Current)

4

Похоже, вы уже поняли virtual и override из своего примера, поэтому:

  • 'abstract' также может применяться к членам вместо 'virtual', и в этом случае вы не укажете реализацию метода (';' непосредственно после подписи). Это заставляет всех конкретных потомков реализовать этот метод.

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

В двух словах;)

1

В дополнение к другим ответам.

Переопределить, если вы хотите разрешить дочерним классам выполнять свою собственную обработку, не обрабатывать или даже просто вызвать обработку родительского класса для функции. Функция переопределения или виртуальная функция не должна выполняться в классах потомков.

Аннотация, когда вы не хотите выполнять какую-либо обработку в базовом классе, но хотите, чтобы этот метод был реализован любым наследующим классом. (Лучше всего, когда поведение наследующего класса может сильно различаться). Если класс содержит только абстрактные методы, то он фактически является типом интерфейса. Функция, указанная как abstract, ДОЛЖНА быть реализована в дочернем классе (компилятор выдаст ошибку, если нет).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню