Каковы реальные примеры абстрактных новых / виртуальных / переопределенных / абстрактных ключевых слов? - PullRequest
2 голосов
/ 16 июня 2009

Я перехожу с PHP на C #.

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

В C #, однако, я потратил около 20 минут, пытаясь найти различные комбинации ключевых слов new , virtual , abstract и override в base и , наследующих классы , пока я, наконец, не получил правильную комбинацию, которая выполняет этот простой каскадный шаблон переопределения.

Так что даже те, которые приведены ниже, работают так, как я хочу, эти добавленные ключевые слова подсказывают мне, что C # может делать гораздо больше с абстрактными классами. Я посмотрел примеры этих ключевых слов и в основном понимаю, что они делают, но все еще не могу представить реальный сценарий, в котором я бы использовал их, кроме этого простого шаблона «каскадного переопределения». Каким образом в реальном мире способов реализации этих ключевых слов в повседневном программировании?

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

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.";
        }
    }

}

Ответы [ 3 ]

8 голосов
/ 16 июня 2009

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

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

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

4 голосов
/ 16 июня 2009

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

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

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

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

1 голос
/ 16 июня 2009

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

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

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

...