Pregunta ¿Cuál es la diferencia entre una función abstracta y una función virtual?


¿Cuál es la diferencia entre una función abstracta y una función virtual? ¿En qué casos se recomienda usar virtual o abstracto? ¿Cuál es el enfoque más correcto?


1304
2017-12-24 14:11


origen


Respuestas:


Una función abstracta no puede tener funcionalidad. Básicamente estás diciendo que cualquier clase infantil DEBE dar su propia versión de este método, sin embargo, es demasiado general como para intentar implementarla en la clase para padres.

Una función virtual, básicamente está diciendo "mira", aquí está la funcionalidad que puede o no ser lo suficientemente buena para la clase infantil. Entonces, si es lo suficientemente bueno, use este método, de lo contrario, anuleme y proporcione su propia funcionalidad.


2325
2017-12-24 14:14



Una función abstracta no tiene implementación y solo se puede declarar en una clase abstracta. Esto fuerza a la clase derivada a proporcionar una implementación. Una función virtual proporciona una implementación predeterminada y puede existir en una clase abstracta o no abstracta. Así por ejemplo:

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();
}

244
2017-12-24 14:19



  1. Solamente abstract las clases pueden tener abstract miembros.
  2. Un no-abstract clase que hereda de un abstract clase debe  override sus abstract miembros.
  3. Un abstract miembro es implícitamente virtual.
  4. Un abstract miembro no puede proporcionar ninguna implementación (abstract se llama pure virtual en algunos idiomas).

68
2018-04-16 09:03



Siempre debe anular una función abstracta.

Así:

  • Funciones abstractas - cuando el heredero debe proporcionar su propia implementación
  • Virtual - cuando le corresponde al heredero decidir

49
2017-12-24 14:13



Función abstracta:

  1. Se puede declarar solo dentro de la clase abstracta.
  2. Solo contiene declaración de método no la implementación en clase abstracta.
  3. Debe ser anulado en clase derivada.

Función virtual:

  1. Se puede declarar dentro de la clase abstracta y no abstracta.
  2. Contiene la implementación del método.
  3. Puede ser anulado.

30
2018-05-28 07:52



Método abstracto: Cuando una clase contiene un método abstracto, esa clase debe declararse como abstracta. El método abstracto no tiene implementación y, por lo tanto, las clases que se derivan de esa clase abstracta deben proporcionar una implementación para este método abstracto.

Método virtual: Una clase puede tener un método virtual. El método virtual tiene una implementación. Cuando heredas de una clase que tiene un método virtual, poder anula el método virtual y proporciona lógica adicional, o reemplaza la lógica con tu propia implementación.

Cuándo usar qué: En algunos casos, usted sabe que ciertos tipos deben tener un método específico, pero no sabe qué implementación debe tener este método.
En tales casos, puede crear una interfaz que contenga un método con esta firma. Sin embargo, si tiene un caso así, pero sabe que los implementadores de esa interfaz también tendrán otro método común (para el cual ya puede proporcionar la implementación), puede crear una clase abstracta. Esta clase abstracta contiene el método abstracto (que debe ser modificado), y otro método que contiene la lógica 'común'.

Se debe usar un método virtual si tiene una clase que se puede usar directamente, pero para la cual desea que los herederos puedan cambiar cierto comportamiento, aunque no es obligatorio.


27
2018-04-16 09:03



explicación: con analogías. con suerte lo ayudará.

Contexto

Yo trabajo en el piso 21 de un edificio. Y estoy paranoico sobre el fuego. De vez en cuando, en algún lugar del mundo, un fuego quema un raspador. Pero afortunadamente tenemos un manual de instrucciones en algún lugar aquí sobre qué hacer en caso de incendio:

Salida de incendios()

  1. No recoger pertenencias
  2. Camina hacia la salida de incendios
  3. Salir de la construcción

Esto es básicamente un método virtual llamado Salida de incendios()

Método virtual

Este plan es bastante bueno para el 99% de las circunstancias. Es un plan básico que funciona. Pero existe un 1% de posibilidades de que la salida de emergencia esté bloqueada o dañada, en cuyo caso estará completamente atornillado y se convertirá en un pan tostado a menos que realice alguna acción drástica. Con los métodos virtuales puede hacer justamente eso: puede anular el plan básico de FireEscape () con su propia versión del plan:

  1. Ejecutar a la ventana
  2. Salta por la ventana
  3. Paracaídas de forma segura hasta el fondo

En otras palabras los métodos virtuales proporcionan un plan básico, que puede ser anulado si necesita. Las subclases pueden anular el método virtual de la clase principal si el programador lo considera apropiado.

Métodos abstractos

No todas las organizaciones están bien perforadas. Algunas organizaciones no hacen simulacros de incendio. No tienen una política de escape general. Cada hombre es para él. La gerencia solo está interesada en que exista dicha política.

En otras palabras, cada persona es forzado para desarrollar su propio método FireEscape (). Un hombre saldrá de la escalera de incendios. Otro chico se lanzará en paracaídas. Otro tipo usará la tecnología de propulsión de cohetes para volar lejos del edificio. Otro tipo se escapará. La gerencia no se preocupa cómo usted escapa, siempre que tenga un plan básico de FireEscape (); si no lo hacen, puede tener la garantía de que OHS caerá en la organización como una tonelada de ladrillos. Esto es lo que significa un método abstracto.

¿Cuál es la diferencia entre los dos nuevamente?

Método abstracto: las subclases son forzado para implementar su propio método FireEscape. Con un método virtual, tiene un plan básico esperando por usted, pero puede elegir para implementar tu propio si no es lo suficientemente bueno

Ahora que no era tan difícil ¿verdad?


23
2018-06-16 01:01



Un método abstracto es un método que debe implementarse para hacer una clase concreta. La declaración está en la clase abstracta (y cualquier clase con un método abstracto debe ser una clase abstracta) y debe implementarse en una clase concreta.

Un método virtual es un método que puede ser anulado en una clase derivada usando la anulación, reemplazando el comportamiento en la superclase. Si no anula, obtiene el comportamiento original. Si lo haces, siempre obtienes el nuevo comportamiento. Esto se opone a los métodos no virtuales, que no pueden anularse pero pueden ocultar el método original. Esto se hace usando el newmodificador

Vea el siguiente ejemplo:

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

Cuando instanciar DerivedClass y llama SayHello, o SayGoodbye, Me pongo "Hola" y "Hasta luego". Si llamo HelloGoodbye, Recibo "Hola" y "Hasta luego". Esto es porque SayGoodbye es virtual y puede ser reemplazado por clases derivadas. SayHello solo está oculto, así que cuando llamo eso desde mi clase base obtengo mi método original.

Los métodos abstractos son implícitamente virtuales. Definen el comportamiento que debe estar presente, más como lo hace una interfaz.


21
2018-04-16 09:13



Los métodos abstractos son siempre virtuales. No pueden tener una implementación.

Esa es la principal diferencia.

Básicamente, usaría un método virtual si tiene la implementación 'predeterminada' y quiere permitir que los descendientes cambien su comportamiento.

Con un método abstracto, fuerza a los descendientes a proporcionar una implementación.


9
2018-04-16 09:00



Hice esto más simple al hacer algunas mejoras en las siguientes clases (de otras respuestas):

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

9
2017-12-07 09:14