Domanda

Qual è la differenza tra una funzione astratta e una funzione virtuale?In quali casi è consigliabile utilizzare virtuale o astratto?Qual è l'approccio migliore?

È stato utile?

Soluzione

Una funzione astratta non può avere funzionalità. Stai fondamentalmente dicendo, ogni classe bambino deve dare la propria versione di questo metodo, tuttavia è troppo generale per cercare anche di implementare nella classe padre.

Una funzione virtuale , è sostanzialmente dicendo sguardo, ecco la funzionalità che può o non può essere abbastanza buono per la classe bambino. Quindi, se è abbastanza buono, utilizzare questo metodo, se no, poi mi ignorare, e di fornire le proprie funzionalità.

Altri suggerimenti

Una funzione astratta non ha L'implementazione e può essere dichiarata solo su una classe astratta. Questo costringe la classe derivata per fornire un'implementazione.

Una funzione virtuale fornisce un'implementazione predefinita e può esistere su entrambi una classe astratta o una classe non astratta.

Così, per esempio:

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. Solo classi abstract possono avere membri abstract.
  2. Una classe non abstract che eredita da una classe abstract deve override i suoi membri abstract.
  3. Un membro abstract è implicitamente virtual.
  4. Un membro abstract non può fornire alcuna implementazione (abstract viene chiamato pure virtual in alcune lingue).

Si deve sempre prevalere una funzione astratta.

In questo modo:

  • Astratto funzioni - quando l'erede deve fornire la propria implementazione
  • virtuale - quando spetta al erede di decidere

Astratto Funzione:

  1. Può essere dichiarata solo dentro classe astratta.
  2. Contiene solo metodo non dichiarazione l'implementazione in classe astratta.
  3. Deve essere sovrascritto in classe derivata.

Virtual Funzione:

  1. Può essere dichiarata all'interno astratto, così come classe non astratta.
  2. Contiene implementazione del metodo.
  3. Può essere ignorata.

metodo astratto: Quando una classe contiene un metodo astratto, che la classe deve essere dichiarato come astratta. Il metodo astratto non ha alcuna implementazione e, quindi, le classi che derivano da tale classe astratta, deve fornire un'implementazione di questo metodo astratto.

metodo virtuale: Una classe può avere un metodo virtuale. Il metodo virtuale ha un'implementazione. Quando si eredita da una classe che ha un metodo virtuale, è possono l'override del metodo virtuale e fornire logica addizionale, o sostituire la logica con la propria implementazione.

Quando utilizzare ciò: In alcuni casi, si sa che certi tipi devono avere un metodo specifico, ma, non so cosa implementazione di questo metodo dovrebbe avere.
In questi casi, è possibile creare un'interfaccia che contiene un metodo con questa firma. Tuttavia, se si dispone di un caso del genere, ma si sa che gli implementatori di tale interfaccia avranno anche un altro metodo comune (per il quale si può già fornire l'attuazione), è possibile creare una classe astratta. Questa classe astratta contiene allora il metodo astratto (che deve essere ignorato), e un altro metodo che contiene la logica 'comune'.

Un metodo virtuale deve essere usato se si dispone di una classe che può essere utilizzato direttamente, ma per il quale si vuole eredi di essere in grado di cambiare certi comportamenti, anche se non è obbligatorio.

spiegazione: con analogie. speriamo che vi aiuterà.

Contesto

Io lavoro al 21 ° piano di un edificio. E io sono paranoico in caso di incendio. Ogni tanto, da qualche parte nel mondo, un incendio sta bruciando un grattacielo. Ma per fortuna abbiamo un manuale di istruzioni da qualche parte qui su cosa fare in caso di incendio:

fireescape ()

  1. Non raccogliere oggetti
  2. A piedi al fuoco di fuga
  3. A piedi fuori di costruzione

Questo è fondamentalmente un metodo virtuale chiamato fireescape ()

Metodo virtuale

Questo piano è abbastanza buona per il 99% delle circostanze. Si tratta di un piano di base che funziona. Ma c'è un 1% di possibilità che la scala antincendio è bloccato o danneggiato, nel qual caso si sono completamente avvitato e si diventerà brindisi a meno che non si prende qualche azione drastica. Con metodi virtuali si può fare proprio questo: è possibile ignorare il piano di base fireescape () con la propria versione del piano:

  1. Esegui per la finestra
  2. saltare fuori dalla finestra
  3. paracadute in modo sicuro al fondo

In altre parole metodi virtuali forniscono un piano di base, che può essere ignorato se è necessario . Le sottoclassi possono eseguire l'override metodo virtuale della classe genitore se il programmatore lo ritenga opportuno.

I metodi astratti

Non tutte le organizzazioni sono ben perforati. Alcune organizzazioni non fanno esercitazioni antincendio. Non hanno una politica globale di fuga. Ogni uomo è per se stesso. Gestione sono interessati solo a una tale politica esistente.

In altre parole, ogni persona è costretto di sviluppare il proprio metodo fireescape (). Un ragazzo sarà uscire dalla scala antincendio. Un altro ragazzo si paracadute. Un altro ragazzo utilizzerà la tecnologia di propulsione a razzo a volare lontano dall'edificio. Un altro ragazzo si calarsi fuori. Gestione non importa come a fuggire, fino a quando si dispone di un piano di base fireescape () - se lo fanno, non si può essere garantito SSL scenderanno sull'organizzazione come una tonnellata di mattoni. Questo è ciò che si intende con un metodo astratto.

Qual è la differenza tra i due di nuovo?

metodo astratto: le sottoclassi sono costretto per implementare il proprio metodo fireescape. Con un metodo virtuale, è necessario un piano di base che ti aspetta, ma può scegliere per implementare il proprio se non è abbastanza buono.

Ora che non era così difficile è stato?

Un metodo astratto è un metodo che deve essere implementata per rendere una classe concreta. La dichiarazione è nella classe astratta (e qualsiasi classe con un metodo astratto deve essere una classe astratta) e deve essere implementato in una classe concreta.

Un metodo virtuale è un metodo che può essere sostituito in una classe derivata usando l'override, sostituendo il comportamento nella superclasse. Se non ignorare, si ottiene il comportamento originale. Se lo fai, si ottiene sempre il nuovo comportamento. Questa differenza di metodi non virtuali, che non possono essere invocati, ma può nascondere il metodo originale. Questo viene fatto usando il modificatore new.

Si veda il seguente esempio:

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

Quando ho un'istanza di DerivedClass e call SayHello, o SayGoodbye, ottengo "Ciao" e "vediamo più tardi". Se chiamo HelloGoodbye, ottengo "Ciao" e "vediamo più tardi". Questo perché SayGoodbye è virtuale, e può essere sostituito da classi derivate. SayHello viene nascosta solo, in modo che quando io lo chiamo dalla mia classe di base ottengo il mio metodo originale.

I metodi astratti sono implicitamente virtuali. Essi definiscono il comportamento che deve essere presente, più come un'interfaccia fa.

I metodi astratti sono sempre virtuali. Essi non possono avere un'implementazione.

Questa è la differenza principale.

In sostanza, si può usare un metodo virtuale se avete la realizzazione 'default' di esso e si desidera consentire discendenti di cambiare il suo comportamento.

Con un metodo astratto, si forza discendenti di fornire un'implementazione.

Ho fatto questo più semplice, facendo alcuni miglioramenti sui seguenti classi (da altre risposte):

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

Binding è il processo di mapping di un nome ad un'unità di codice.

L'associazione tardiva significa che usiamo il nome, ma rinviare la mappatura. In altre parole, creiamo / menzionare il nome prima, e lasciare che qualche processo successivo di gestire la mappatura di codice per quel nome.

Consideriamo ora:

  • Rispetto per l'uomo, le macchine sono veramente bravo a ricerca e l'ordinamento
  • Rispetto alle macchine, gli esseri umani sono veramente bravo a invenzione e innovazione

Quindi, la risposta breve è: virtual è un'istruzione associazione tardiva per la macchina (runtime), mentre abstract è l'istruzione vincolante in ritardo per l'uomo (programmatore)

In altre parole, significa virtual:

“Caro runtime , legano il codice appropriato a questo nome per fare quello che sai fare meglio: ricerca

considerando che abstract significa:

“Caro programmatore , si prega di legare il codice appropriato a questo nome per fare quello che sai fare meglio: inventare

Per ragioni di completezza, sovraccarico significa:

“Caro compilatore , legano il codice appropriato a questo nome per fare quello che sai fare meglio: ordinamento ”.

È fondamentalmente utilizzare un metodo virtuale in cui si desidera che le eredi di estendere le funzionalità, se vogliono.

Si utilizza metodi astratti quando si vuole gli eredi per implementare la funzionalità (e in questo caso non hanno scelta)

Ho visto che in alcuni punti il ​​metodo astratto è definito come di seguito.**

"Un metodo astratto deve essere implementato nella classe figlia"

** Ho sentito che è come .

Non è necessario che un metodo astratto debba essere implementato in una classe figlia, se anche la classe figlia è astratta ..

1)Un metodo astratto non posso essere un metodo privato.2)Un metodo astratto non posso essere implementato nella stessa classe astratta.

Direi che... se stiamo implementando una classe astratta, è necessario sovrascrivere i metodi astratti dalla classe astratta di base.Perché..L'implementazione del metodo astratto è con oltrepassare parola chiave. Simile al metodo virtuale.

Non è necessario che un metodo virtuale sia implementato in una classe ereditata.

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

Metodo virtuale :

  • mezzi virtuali possiamo ignorarlo.

  • Virtual funzione ha un'implementazione. Quando noi ereditiamo la classe che può ignorare la funzione virtuale e fornire la nostra logica.

  • Siamo in grado di cambiare il tipo di ritorno della funzione virtuale, mentre l'attuazione del
    funzione nella classe figlia (che può essere detto come un concetto di
    Shadowing).

metodo astratto

  • abstract significa che dobbiamo ignorare esso.

  • Una funzione astratta non ha alcuna implementazione e deve essere in una classe astratta.

  • Si può essere dichiarata solo. Questo costringe la classe derivata per fornire l'attuazione di esso.

  • Un membro astratta è implicitamente virtuale. L'abstract può essere chiamato come puro virtuale in alcune delle lingue.

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

Funzione astratta non può avere un corpo e DEVE essere sovrascritto dalle classi figlie

Funzione virtuale avrà un corpo e potrà o meno essere sovrascritto dalle classi figlie

La maggior parte degli esempi di cui sopra utilizzare codice - e sono molto, molto buono. Non ho bisogno di aggiungere a quello che si dice, ma la seguente è una spiegazione semplice che fa uso di analogie piuttosto che termini codice / tecnico.

semplice spiegazione - Spiegazione utilizzando analogie

metodo astratto

Si pensi George W. Bush. Egli dice ai suoi soldati: "andare a combattere in Iraq". E questo è tutto. Tutto quello che ha precisato è che la lotta deve essere fatto. Egli non specifica come esattamente che accadrà. Ma voglio dire, non si può semplicemente uscire e "combattere": che cosa significa esattamente? faccio a combattere con un B-52 o il mio Derringer? Questi dettagli specifici sono lasciati a qualcun altro. Questo è un metodo astratto.

Metodo virtuale

David Petraeus è in alto nell'esercito. Egli ha definito che cosa significa lotta:

  1. Trova il nemico
  2. lo Neutralizzare.
  3. Avere una birra dopo

Il problema è che si tratta di un metodo molto generale. E 'un buon metodo che funziona, ma a volte non è abbastanza specifico. Buona cosa per Petraeus è che i suoi ordini hanno libertà d'azione e la portata -. Ha permesso ad altri di cambiare la sua definizione di "combattere", in base alle loro particolari esigenze

Privato lavoro Bloggs legge ordine Petraeus' ed è dato il permesso di implementare la propria versione di lotta, secondo le sue esigenze particolari:

  1. Trova nemico.
  2. sparategli in testa.
  3. Vai a casa
  4. Avere birra.

Nouri al Maliki riceve anche gli stessi ordini da Petraeus. Egli è quello di combattere anche. Ma lui è un politico, non un uomo di fanteria. Ovviamente non può andare in giro a sparare i suoi nemici Politican nella testa. Perché Petraeus gli ha dato un metodo virtuale, quindi Maliki in grado di implementare la propria versione del metodo di lotta, in base alle sue condizioni:

  1. Trova nemico.
  2. farlo arrestare con qualche BS trumped di cariche.
  3. Vai a casa
  4. Avere birra.

In altre parole, un metodo virtuale fornisce istruzioni boilerplate -. Ma queste sono le istruzioni generali, che possono essere fatte in modo più preciso da parte di persone lungo la gerarchia dell'esercito, secondo le loro circostanze particolari

La differenza tra i due

  • George Bush non prova alcun dettagli di implementazione. Questo deve essere fornita da qualcun altro. Questo è un metodo astratto.

  • Petraeus d'altra parte non di fornire i dettagli di implementazione ma ha dato il permesso per i suoi subordinati di ignorare i suoi ordini con la propria versione, se possono venire con qualcosa di meglio.

speranza che aiuta.

Astratto funzione (metodo):

● un metodo astratto è un metodo che viene dichiarato con la parola chiave astratta.

● Non ha corpo.

● Dovrebbe essere implementata dalla classe derivata.

● Se un metodo è astratto allora la classe dovrebbe astratta.

funzione virtuale (metodo):

● Un metodo virtuale è il metodo che viene dichiarato con la parola chiave virtuale e può essere sovrascritto con il metodo della classe derivata utilizzando esclusione parola chiave.

● E 'fino alla classe derivata se sostituire o meno.

La risposta è stata fornita di un certo numero di volte, ma la domanda su quando utilizzare ciascuno è una decisione di progettazione. Vedrei come buona norma cercare di raggruppare definizioni comuni metodi nelle interfacce distinte e tirare in classi di appropriati livelli di astrazione. Di dumping un insieme comune di definizioni astratte e virtuali metodo in una classe rende l'unistantiable classe quando può essere meglio definire una classe non astratta che implementa un insieme di interfacce concisi. Come sempre, dipende da quello che meglio si adatta alle vostre applicazioni specifiche esigenze.

Da object oriented vista generale:

Per quanto riguarda metodo astratto : Quando si inserisce un metodo astratto nella classe padre in realtà il tuo stanno dicendo alle classi figlie: Hey notare che si dispone di una firma del metodo come questo. E se vuoi usarlo è necessario implementare i vostri!

Per quanto riguarda la funzione virtuale : Quando si inserisce un metodo virtuale nella classe padre si sta dicendo alle classi derivate: Hey v'è una funzionalità che qui fare qualcosa per voi. Se questo è utile per voi solo utilizza. In caso contrario, ignorare questa e implementare il codice, anche si può usare la mia implementazione nel codice!

questo è un po 'di filosofia merito ad una diversa tra questa due concept in generale OO

Ci sono niente di chiamata classe virtuale in C #.

Per le funzioni

  1. Astratto funzione hanno solo la firma solo, la classe unità dovrebbe sovrascrivere con la funzionalità.
  2. Funzione virtuale si terrà la parte della funzionalità della classe unità può o non può ignorare che in base al requisito

Si può decidere con il vostro requisito.

metodo astratto Non ha un implementation.It viene dichiarato nella classe padre. La classe bambino è resposible per attuazione di tale metodo.

metodo virtuale dovrebbe avere un'implementazione nella classe padre e facilita la classe figlia per fare la scelta se utilizzare tale implementazione della classe genitore o di avere una nuova implementazione per se stessa per quel metodo in classe figlia.

Una funzione astratta è "solo" una firma, senza un implementazione. E 'utilizzato in un'interfaccia di dichiarare come la classe può essere utilizzato. Si deve essere attuato in una delle classi derivate.

funzione virtuale (metodo in realtà), è una funzione si dichiara pure, e dovrebbe implementato in una delle classi gerarchia di ereditarietà.

Le istanze ereditarie di tale classe, ereditano l'attuazione e, a meno che non si implementa che, in una classe inferiore della gerarchia.

Da uno sfondo C ++, C # corrisponde virtuali a C ++ virtuale, mentre i metodi astratti C # corrisponde alla funzione virtuale pura C ++

Una funzione astratta o metodo è "nome operazione" un pubblico esposto da una classe, il suo scopo, insieme alle classi astratte, è principalmente fornire una forma di vincolo nel disegno oggetti contro la struttura che un oggetto deve implementare.

In realtà le classi che ereditano dalla classe astratta devono dare un'implementazione di questo metodo, in genere compilatori generare errori quando non lo fanno.

Uso classi e metodi astratti è importante soprattutto per evitare che puntando sulla dettagli di implementazione quando si progetta classi, la struttura classi essere troppo legata alle implementazioni, così creando dipendenze e accoppiamento tra le classi che collaborano tra loro.

Una funzione virtuale o di un metodo è semplicemente un metodo che modella un comportamento pubblico di una classe, ma che possono lasciare liberi di modificarlo nella catena di ereditarietà, perché pensiamo che le classi bambino potrebbe avere necessario implementare alcune estensioni specifiche per quel comportamento.

Entrambi rappresentano una forma di polymorpfhism in oggetto orientamento paradigma.

Possiamo usare metodi astratti e funzioni virtuali insieme per sostenere un buon modello di ereditarietà.

Progettiamo una buona struttura astratta di oggetti principali della nostra soluzione, quindi creare le implementazioni di base, individuando quelli più inclini a ulteriori specializzazioni e facciamo questi come virtuali, finalmente ci siamo specializzati nostre implementazioni di base, eventyually "prevalente" ereditato quelle virtuali .

Qui sto scrivendo alcuni esempi di codice sperando questo può essere un esempio piuttosto concreto di vedere i comportamenti delle interfacce, classi astratte e le classi ordinarie a un livello di base. È inoltre possibile trovare questo codice in github come progetto se si desidera utilizzarlo come demo: 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(){
    //
    //    }
    }
}

Per la mia comprensione:

metodi astratti:

Solo la classe astratta può contenere metodi astratti. Anche la classe derivata deve implementare il metodo e nessuna implementazione è prevista nella classe.

Metodi virtuali:

Una classe può dichiarare questi e anche fornire l'attuazione dello stesso. Anche la classe derivata deve implementare il metodo per eseguire l'override di esso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top