c# - пример - отличие абстрактного класса от интерфейса java 8




В чем разница между абстрактной функцией и виртуальной функцией? (16)

  1. Только abstract классы могут иметь abstract членов.
  2. Не abstract класс, который наследуется от abstract класса, должен override его abstract члены.
  3. abstract элемент неявно virtual .
  4. abstract элемент не может обеспечить никакой реализации ( abstract называется pure virtual на некоторых языках).

В чем разница между абстрактной функцией и виртуальной функцией? В каких случаях рекомендуется использовать виртуальные или абстрактные? Какой правильный подход?


Абстрактная функция (метод):

● Абстрактный метод - это метод, который объявляется с помощью абстрактного ключевого слова.

● У него нет тела.

● Он должен быть реализован производным классом.

● Если метод является абстрактным, класс должен абстрагироваться.

виртуальная функция (метод):

● Виртуальным методом является метод, объявленный с ключевым словом virtual, и его можно переопределить методом производного класса с помощью ключевого слова override.

● Это зависит от производного класса, следует ли его переопределить или нет.


Абстрактная функция не имеет реализации и может быть объявлена ​​только в абстрактном классе. Это заставляет производный класс обеспечивать реализацию. Виртуальная функция предоставляет реализацию по умолчанию и может существовать либо в абстрактном классе, либо в неабстрактном классе. Так, например:

public abstract class myBase
{
    //If you derive from this class you must implement this method. notice we have no method body here either
    public abstract void YouMustImplement();

    //If you derive from this class you can change the behavior but are not required to
    public virtual void YouCanOverride()
    { 
    }
}

public class MyBase
{
   //This will not compile because you cannot have an abstract method in a non-abstract class
    public abstract void YouMustImplement();
}

Абстрактная функция:

  1. Он может быть объявлен только внутри абстрактного класса.
  2. Он содержит только объявление метода, а не реализацию в абстрактном классе.
  3. Он должен быть переопределен в производном классе.

Виртуальная функция:

  1. Он может быть объявлен как внутри абстрактного, так и не абстрактного класса.
  2. Он содержит реализацию метода.
  3. Это может быть отменено.

Абстрактный метод не имеет реализации. Он объявлен в родительском классе. Детский класс применим для реализации этого метода.

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


Абстрактный метод. Когда класс содержит абстрактный метод, этот класс должен быть объявлен как абстрактный. Абстрактный метод не имеет реализации и, следовательно, классы, которые происходят из этого абстрактного класса, должны обеспечить реализацию этого абстрактного метода.

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

Когда использовать то, что: В некоторых случаях вы знаете, что определенные типы должны иметь определенный метод, но вы не знаете, какую реализацию должен иметь этот метод.
В таких случаях вы можете создать интерфейс, содержащий метод с этой сигнатурой. Однако, если у вас есть такой случай, но вы знаете, что разработчики этого интерфейса также будут иметь еще один распространенный метод (для которого вы уже можете обеспечить реализацию), вы можете создать абстрактный класс. Этот абстрактный класс затем содержит абстрактный метод (который должен быть переопределен) и другой метод, который содержит «общую» логику.

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


Большинство приведенных выше примеров используют код - и они очень хороши. Мне не нужно добавлять к тому, что они говорят, но следующее - простое объяснение, которое использует аналогии, а не код / ​​технические термины.

Простое объяснение - Объяснение с использованием аналогов

Абстрактный метод

Подумайте, Джордж Буш. Он говорит своим солдатам: «Иди бой в Ираке». И это все. Все, что он указал, - это то, что нужно сражаться. Он не уточняет, как именно это произойдет. Но я имею в виду, вы не можете просто выйти и «драться»: что это значит? я сражаюсь с B-52 или моим derringer? Эти конкретные детали оставлены кому-то еще. Это абстрактный метод.

Виртуальный метод

Дэвид Петреус высоко в армии. Он определил, что значит борьба:

  1. Найти врага
  2. Нейтрализовать его.
  3. Выпить пива после

Проблема в том, что это очень общий метод. Это хороший метод, который работает, но иногда не является достаточно конкретным. Хорошая вещь для Петреуса заключается в том, что его приказы имеют свободу действий и возможности - он позволил другим изменить свое определение «битвы» в соответствии с их особыми требованиями.

Частная работа Bloggs читает заказ Петреуса и получает разрешение на реализацию своей собственной версии боя в соответствии с его особыми требованиями:

  1. Найдите врага.
  2. Стреляйте в голову.
  3. Иди домой
  4. Пиво.

Нури аль Малики также получает те же заказы от Петреуса. Он также должен сражаться. Но он политик, а не пехотный. Очевидно, он не может стрелять в своих политических врагов в голову. Поскольку Петреус дал ему виртуальный метод, Малики может реализовать свою собственную версию метода боя в соответствии с его конкретными обстоятельствами:

  1. Найдите врага.
  2. Попросите его арестовать несколько обвиненных BS.
  3. Иди домой
  4. Пиво.

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

Разница между двумя

  • Джордж Буш не доказывает детали реализации. Это должно быть сделано кем-то другим. Это абстрактный метод.

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

надеюсь, это поможет.


В C # ничего не называют виртуальным классом.

Для функций

  1. Абстрактная функция имеет только подпись, класс диска должен переопределяться с функциональностью.
  2. Виртуальная функция будет удерживать часть функциональности, которую класс диска может или не может переопределить в соответствии с требованием

Вы можете решить свои требования.


Вы всегда должны переопределять абстрактную функцию.

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

  • Абстрактные функции - когда наследник должен обеспечить свою собственную реализацию
  • Виртуальный - когда решение зависит от наследника

Из общего объектно-ориентированного представления:

Что касается абстрактного метода : когда вы помещаете абстрактный метод в родительский класс, на самом деле вы говорите дочерним классам: Эй, обратите внимание, что у вас есть подпись метода, подобная этому. И если вы хотите использовать его, вы должны реализовать свои собственные!

Что касается виртуальной функции : когда вы помещаете виртуальный метод в родительский класс, вы говорите производным классам: Эй, здесь есть функция, которая что-то делает для вас. Если это полезно, просто используйте его. Если нет, переопределите это и внесите свой код, даже вы можете использовать мою реализацию в вашем коде!

это какая-то философия о различии между этими двумя понятиями в General OO


Объяснение: с аналогиями. надеюсь, это поможет вам.

контекст

Я работаю на 21-м этаже здания. И я параноик о пожаре. Время от времени, где-то в мире, огонь сжигает небоскреб. Но, к счастью, у нас есть инструкция по работе где-то здесь, что делать в случае пожара:

Пожарный выход()

  1. Не собирайте вещи
  2. Прогулка до пожара
  3. Выход из строя

Это в основном виртуальный метод FireEscape ()

Виртуальный метод

Этот план довольно хорош для 99% обстоятельств. Это основной план, который работает. Но есть 1% -ый шанс того, что пожарный выход заблокирован или поврежден, и в этом случае вы полностью завинчены, и вы станете тостом, если не предпримете какие-то решительные действия. С помощью виртуальных методов вы можете сделать именно это: вы можете переопределить базовый план FireEscape () своей собственной версией плана:

  1. Запустить в окно
  2. Выпрыгнуть в окно
  3. Парашют безопасно снизу

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

Абстрактные методы

Не все организации хорошо просверлены. Некоторые организации не выполняют противопожарные упражнения. У них нет общей политики побега. Каждый человек для себя. Руководство заинтересовано только в такой политике.

Другими словами, каждый человек вынужден разработать свой собственный метод FireEscape (). Один парень выйдет из пожарной лестницы. Другой парень будет парашютом. Другой парень будет использовать ракетные двигательные технологии, чтобы улететь из здания. Другой парень исчезнет. Менеджменту все равно, как вы избегаете, если у вас есть базовый план FireEscape (), если они не могут быть гарантированы. OHS придет к организации, как тонна кирпичей. Это то, что подразумевается под абстрактным методом.

В чем разница между ними снова?

Абстрактный метод: подклассы вынуждены реализовать свой собственный метод FireEscape. С помощью виртуального метода у вас есть базовый план, ожидающий вас, но вы можете реализовать его самостоятельно, если он недостаточно хорош.

Теперь это было не так сложно?


Ответ был предоставлен несколько раз, но вопрос о том, когда использовать каждый, - это решение времени разработки. Я считаю хорошей практикой попытаться объединить общие определения методов в разные интерфейсы и потянуть их в классы с соответствующими уровнями абстракции. Сбрасывание общего набора абстрактных и виртуальных определений методов в класс делает класс неустойчивым, когда лучше всего определить не-абстрактный класс, реализующий набор сжатых интерфейсов. Как всегда, это зависит от того, что лучше всего подходит вашим приложениям.


Я видел в некоторых местах абстрактный метод, как показано ниже. **

«Абстрактный метод должен реализовывать в дочернем классе»

** Я чувствовал, что это похоже.

Нет необходимости, чтобы абстрактный метод был реализован в дочернем классе, если дочерний класс также является абстрактным .

1) Абстрактный метод can not может быть приватным методом. 2) Абстрактный метод не может быть реализован в том же абстрактном классе.

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

Не обязательно, чтобы виртуальный метод был реализован в унаследованном классе.

                                 ----------CODE--------------

public abstract class BaseClass
{
    public int MyProperty { get; set; }
    protected abstract void MyAbstractMethod();

    public virtual void MyVirtualMethod()
    {
        var x = 3 + 4;
    }

}
public abstract class myClassA : BaseClass
{
    public int MyProperty { get; set; }
    //not necessary to implement an abstract method if the child class is also abstract.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}
public class myClassB : BaseClass
{
    public int MyProperty { get; set; }
    //You must have to implement the abstract method since this class is not an abstract class.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}

Я сделал это проще, сделав некоторые улучшения в следующих классах (из других ответов):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestOO
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseClass _base = new BaseClass();
            Console.WriteLine("Calling virtual method directly");
            _base.SayHello();
            Console.WriteLine("Calling single method directly");
            _base.SayGoodbye();

            DerivedClass _derived = new DerivedClass();
            Console.WriteLine("Calling new method from derived class");
            _derived.SayHello();
            Console.WriteLine("Calling overrided method from derived class");
            _derived.SayGoodbye();

            DerivedClass2 _derived2 = new DerivedClass2();
            Console.WriteLine("Calling new method from derived2 class");
            _derived2.SayHello();
            Console.WriteLine("Calling overrided method from derived2 class");
            _derived2.SayGoodbye();
            Console.ReadLine();
        }
    }


    public class BaseClass
    {
        public void SayHello()
        {
            Console.WriteLine("Hello\n");
        }
        public virtual void SayGoodbye()
        {
            Console.WriteLine("Goodbye\n");
        }

        public void HelloGoodbye()
        {
            this.SayHello();
            this.SayGoodbye();
        }
    }


    public abstract class AbstractClass
    {
        public void SayHello()
        {
            Console.WriteLine("Hello\n");
        }


        //public virtual void SayGoodbye()
        //{
        //    Console.WriteLine("Goodbye\n");
        //}
        public abstract void SayGoodbye();
    }


    public class DerivedClass : BaseClass
    {
        public new void SayHello()
        {
            Console.WriteLine("Hi There");
        }

        public override void SayGoodbye()
        {
            Console.WriteLine("See you later");
        }
    }

    public class DerivedClass2 : AbstractClass
    {
        public new void SayHello()
        {
            Console.WriteLine("Hi There");
        }
        // We should use the override keyword with abstract types
        //public new void SayGoodbye()
        //{
        //    Console.WriteLine("See you later2");
        //}
        public override void SayGoodbye()
        {
            Console.WriteLine("See you later");
        }
    }
}

Абстрактная функция не может иметь тело и ДОЛЖНА быть переопределена дочерними классами

Виртуальная функция будет иметь тело и может или не может быть переопределена дочерними классами


Виртуальный метод :

  • Virtual означает, что мы МОЖЕМ переопределить его.

  • Виртуальная функция имеет реализацию. Когда мы наследуем класс, мы можем переопределить виртуальную функцию и предоставить свою собственную логику.

  • Мы можем изменить возвращаемый тип виртуальной функции при реализации
    функции в дочернем классе (который можно назвать понятием
    Затенение).

Абстрактный метод

  • Абстрактный означает, что мы ДОЛЖНЫ переопределить его.

  • Абстрактная функция не имеет реализации и должна быть в абстрактном классе.

  • Он может быть объявлен только. Это заставляет производный класс обеспечивать его реализацию.

  • Абстрактный элемент неявно виртуальный. Реферат можно назвать чистым виртуальным на некоторых языках.

    public abstract class BaseClass
    { 
        protected abstract void xAbstractMethod();
    
        public virtual void xVirtualMethod()
        {
            var x = 3 + 4;
        }
    } 
    




virtual-functions