В чем разница между абстрактным методом и виртуальным методом?

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


person Moran Helman    schedule 24.12.2008    source источник
comment
Абстрактная функция должна быть переопределена, а виртуальная функция может быть переопределена.   -  person Jordan Parmer    schedule 24.12.2008
comment
Виртуальные функции могут иметь стандартную / общую реализацию в базовом классе.   -  person Martin    schedule 05.12.2012
comment
Ключевое слово здесь - абстрактный; Их не существует, и они представляют собой лишь смутное представление о том, что это за функция (сигнатура метода).   -  person Cole Johnson    schedule 28.05.2017


Ответы (28)


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

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

person BFree    schedule 24.12.2008
comment
И, конечно же, если вы переопределите виртуальный метод, вы всегда можете обратиться к родительскому методу, вызвав base.Foo (...) - person Brann; 05.07.2011
comment
Спасибо. Это гораздо лучшее и простое объяснение, чем что-либо в документации MSDN (у меня заболела голова после пяти минут чтения этого: msdn.microsoft.com/en-us/library/aa645767 (v = vs.71) .aspx) - person Jake; 01.11.2011
comment
Исходя из Java, я был немного озадачен, почему нам вообще нужно делать его виртуальным, пока я не прочитал это: stackoverflow.com/a/ 1062126/193634 - person Rosdi Kasim; 17.04.2013
comment
@MeqDotNet Это означает, что если вам нравится моя реализация, используйте меня, если НЕ напишите свое лучше, чем я :) - person Usman Younas; 06.11.2013
comment
Вам также необходимо пометить свой родительский класс как абстрактный, чтобы заставить дочерний класс реализовать все абстрактные методы / функции. - person mjb; 20.01.2014
comment
Это должно быть в справочной библиотеке Microsoft, которую я читал 10 минут и все еще не понимал. - person SamChen; 28.05.2014
comment
очень хороший пост, но я думаю, что лучше сказать Абстрактная функция Должна не иметь функциональности. - person Ayub; 01.01.2015
comment
Возможно, стоит упомянуть, что вызывающая головную боль документация MSDN по virtual, на которую ссылался Джейк выше, была взята из документации 2003 года. Следующая ссылка MSDN из документации 2013 года объясняет ситуацию немного проще: msdn.microsoft. ru / en-us / library / 9fkccyh4.aspx - person StackOverflowUser; 11.01.2015
comment
Почему по умолчанию не все методы виртуальны? Речь идет не о том, чтобы понравиться какой-либо реализации, а о полиморфизме - или возможности блокировки любого полиморфизма, не отмечая методы как виртуальные, тем самым отрицая возможность их расширения. - person mvmn; 01.06.2017
comment
@mvmn В C ++ создание метода виртуальным требует затрат - экземпляр производного класса должен проверить, какую функцию вызывать (свою собственную или одну из его предков). В S O LID принципах O является OpenClosed - открыт для расширения, закрыт для модификации. Если вы хотите следовать этому принципу, вы не хотите, чтобы кто-то переопределил методы ваших классов (или даже унаследовал их). - person nitzel; 08.03.2018
comment
Разве вы не можете сделать их закрытыми для отмены? - person mvmn; 25.04.2018
comment
Абстрактная функция похожа на чистую виртуальную функцию в C ++. - person Lil Taco; 30.06.2018
comment
очень красивое объяснение. Это должно быть в MSDN. - person MING WU; 27.05.2020

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

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

Так например:

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();
}
person JoshBerke    schedule 24.12.2008
comment
Очень полезно увидеть образец кода - помогает сделать различные объяснения в ответах более понятными. - person Simon Tewsi; 23.01.2013
comment
Я откатил ответ на предыдущую версию: два класса - просто примеры, первый класс будет компилироваться, так как он помечен как абстрактный, второй - нет. Наследуется ли MyBase от другого класса или нет, не имеет значения. - person Dirk; 12.06.2014
comment
Разве ваш MyBase класс не должен каким-то образом реализовывать класс abstract? Я делаю это не часто, поэтому могу ошибаться. Я не вижу этого в вашем примере. - person jp2code; 27.06.2014
comment
В приведенном выше примере MyBase показывает, что вы не можете сделать. То есть у вас не может быть абстрактного метода в не абстрактном классе - person JoshBerke; 28.06.2014

  1. Только abstract классы могут иметь abstract членов.
  2. Класс, не являющийся abstract, который наследуется от abstract класса, должен override его abstract члены.
  3. Член abstract неявно означает virtual.
  4. Член abstract не может предоставить какую-либо реализацию (abstract в некоторых языках называется pure virtual).
person mmx    schedule 16.04.2009
comment
Номер 3 для меня не имеет смысла. Я думаю, вы хотели сказать, что член абстрактного класса неявно виртуален (т.е. вы можете предоставить ему функциональные возможности, не указывая, что он виртуальный). - person Hobo Spider; 14.01.2014
comment
Нет, я имел в виду именно то, что написал. Член абстрактного класса может быть virtual или не virtual. Член abstract (т.е. абстрактное свойство, абстрактный метод) подобен виртуальному методу, то есть вы можете переопределить его, за исключением того, что он не несет в себе реализацию по умолчанию. - person mmx; 15.01.2014
comment
Цитируемый абстрактный член неявно виртуален. Но я где-то видел, что кто-то создал абстрактные члены, явно добавив ключевое слово virtual. В этом нет необходимости, и на самом деле это вызвало у меня сомнения, пока я не прочитал ваш ответ. - person bonCodigo; 20.05.2014
comment
Пожалуйста, включите вспомогательные ссылки для пункта 4. И ваш пост не приносит ничего, кроме предыдущих. - person Rafael; 27.11.2017
comment
Это просто набор утверждений без объяснения причин. - person Reverse Engineered; 19.02.2020

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

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

  • Абстрактные функции - когда наследник должен предоставить свою собственную реализацию
  • Виртуальный - когда решение остается за наследником
person Rinat Abdullin    schedule 24.12.2008

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

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

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

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

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

Контекст

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

FireEscape ()

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

По сути, это виртуальный метод под названием FireEscape ().

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

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

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

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

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

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

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

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

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

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

person BKSpurgeon    schedule 16.06.2016

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

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

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

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

person Frederik Gheysels    schedule 16.04.2009

Абстрактный метод - это метод, который необходимо реализовать для создания конкретного класса. Объявление находится в абстрактном классе (и любой класс с абстрактным методом должен быть абстрактным классом), и он должен быть реализован в конкретном классе.

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

См. Следующий пример:

public class BaseClass
{
    public void SayHello()
    {
        Console.WriteLine("Hello");
    }


    public virtual void SayGoodbye()
    {
        Console.WriteLine("Goodbye");
    }

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


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


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

Когда я создаю экземпляр DerivedClass и звоню SayHello или SayGoodbye, я получаю «Привет!» И «Увидимся позже». Если я звоню HelloGoodbye, я получаю «Привет» и «Увидимся позже». Это потому, что SayGoodbye является виртуальным и может быть заменен производными классами. SayHello только скрыт, поэтому, когда я вызываю его из своего базового класса, я получаю свой исходный метод.

Абстрактные методы неявно виртуальны. Они определяют поведение, которое должно присутствовать, больше похоже на интерфейс.

person Kamiel Wanrooij    schedule 16.04.2009

Абстрактные методы всегда виртуальны. У них не может быть реализации.

В этом главное отличие.

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

С помощью абстрактного метода вы заставляете потомков предоставлять реализацию.

person Rashack    schedule 16.04.2009

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

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");
        }
    }
}
person MeqDotNet    schedule 07.12.2011

Привязка - это процесс сопоставления имени с единицей кода.

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

Теперь рассмотрим:

  • По сравнению с людьми машины действительно хороши в поиске и сортировке.
  • По сравнению с машинами люди действительно хороши в изобретениях и инновациях.

Итак, краткий ответ: virtual - это инструкция позднего связывания для машины (среда выполнения), тогда как abstract - инструкция позднего связывания для человека (программиста).

Другими словами, virtual означает:

«Уважаемая среда выполнения, привяжите соответствующий код к этому имени, делая то, что у вас получается лучше всего: поиск»

Принимая во внимание, что abstract означает:

«Уважаемый программист, привяжите соответствующий код к этому имени, делая то, что у вас получается лучше всего: изобретать»

Для полноты картины перегрузка означает:

«Уважаемый компилятор, привяжите соответствующий код к этому имени, выполнив то, что у вас лучше всего получается: сортировка».

person Rodrick Chapman    schedule 13.08.2017

Вы в основном используете виртуальный метод, когда хотите, чтобы наследники расширили функциональность, ЕСЛИ они захотят.

Вы используете абстрактные методы, когда хотите, чтобы наследники реализовали функциональность (и в этом случае у них нет выбора)

person Brann    schedule 16.04.2009

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

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

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

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

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

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

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

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

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

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

Я видел в некоторых местах, что абстрактный метод определяется следующим образом. **

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

** Я чувствовал, что это нравится.

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

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

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

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

                                 ----------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();
    }
}
person Kod    schedule 05.08.2015

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

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

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

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

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

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

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

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

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

  1. Найди врага.
  2. Выстрелите ему в голову.
  3. Иди домой
  4. Выпей пива.

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

  1. Найди врага.
  2. Его арестуют по сфабрикованным обвинениям.
  3. Иди домой
  4. Выпей пива.

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

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

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

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

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

person BKSpurgeon    schedule 06.05.2016

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

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

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

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

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

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

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

● Производный класс решает, переопределять его или нет.

person Kedarnath M S    schedule 31.05.2016

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

person ComeIn    schedule 19.08.2013

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

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

person Yeasin Abedin Siam    schedule 12.01.2016

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

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

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

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

person Mohammad Nikravesh    schedule 01.03.2017

Абстрактная функция - это «просто» подпись без реализации. Он используется в интерфейсе, чтобы объявить, как можно использовать класс. Он должен быть реализован в одном из производных классов.

Виртуальная функция (фактически метод) - это функция, которую вы также объявляете, и она должна быть реализована в одном из классов иерархии наследования.

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

person Sagi Berco    schedule 27.07.2018

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

person x-rw    schedule 10.09.2019

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

Для функций

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

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

person Nithila Shanmugananthan    schedule 07.06.2016

У абстрактного метода нет реализации, он объявлен в родительском классе. Дочерний класс отвечает за реализацию этого метода.

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

person Vinay Chanumolu    schedule 05.06.2018

Исходя из фона C ++, виртуальный C # соответствует виртуальному C ++, а абстрактные методы C # соответствуют чистой виртуальной функции C ++.

person Yituo    schedule 27.10.2018

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

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

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

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

Оба они представляют собой форму полиморфизма в парадигме объектной ориентации.

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

Мы проектируем хорошую абстрактную структуру основных объектов нашего решения, затем создаем базовые реализации, определяя те, которые более склонны к дальнейшей специализации, и делаем их виртуальными, наконец, мы специализируем наши базовые реализации, в конечном итоге «отменяя» унаследованные виртуальные.

person Ciro Corvino    schedule 24.02.2019

Здесь я пишу пример кода, надеясь, что это может быть довольно ощутимый пример, позволяющий увидеть поведение интерфейсов, абстрактных классов и обычных классов на самом базовом уровне. Вы также можете найти этот код в github как проект, если хотите использовать его в качестве демонстрации: https://github.com/usavas/JavaAbstractAndInterfaceDemo

public interface ExampleInterface {

//    public void MethodBodyInInterfaceNotPossible(){
//    }
    void MethodInInterface();

}

public abstract class AbstractClass {
    public abstract void AbstractMethod();

    //    public abstract void AbstractMethodWithBodyNotPossible(){
    //
    //    };

    //Standard Method CAN be declared in AbstractClass
    public void StandardMethod(){
        System.out.println("Standard Method in AbstractClass (super) runs");
    }
}

public class ConcreteClass
    extends AbstractClass
    implements ExampleInterface{

    //Abstract Method HAS TO be IMPLEMENTED in child class. Implemented by ConcreteClass
    @Override
    public void AbstractMethod() {
        System.out.println("AbstractMethod overridden runs");
    }

    //Standard Method CAN be OVERRIDDEN.
    @Override
    public void StandardMethod() {
        super.StandardMethod();
        System.out.println("StandardMethod overridden in ConcreteClass runs");
    }

    public void ConcreteMethod(){
        System.out.println("Concrete method runs");
    }

    //A method in interface HAS TO be IMPLEMENTED in implementer class.
    @Override
    public void MethodInInterface() {
        System.out.println("MethodInInterface Implemented by ConcreteClass runs");

    //    Cannot declare abstract method in a concrete class
    //    public abstract void AbstractMethodDeclarationInConcreteClassNotPossible(){
    //
    //    }
    }
}
person U.Savas    schedule 02.03.2019

Методы можно разделить в зависимости от обязательности / их отсутствия и разрешения / их отмены:

  • абстрактный (чистый) / конкретный (нечистый): должен быть изменен / не может быть изменен;
  • виртуальный / реальный: можно переопределить / нельзя переопределить.

Итак, по определению абстрактные методы могут быть только виртуальными, а реальные методы могут быть только конкретными.

person Maggyero    schedule 13.05.2021

Насколько я понимаю:

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

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

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

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

person Qaiser    schedule 27.06.2011