Domanda

Ok, porta con me ragazzi e ragazze mentre sto imparando. Ecco la mia domanda.

Non riesco a capire perché non posso ignorare un metodo da una classe genitore. Ecco il codice della classe base (sì, ho rubato il codice java da un libro OOP e sto provando a riscriverlo in C #).

using System;

public class MoodyObject
{
    protected String getMood()
    {
        return "moody";
    }

    public void queryMood()
    {
        Console.WriteLine("I feel " + getMood() + " today!");
    }
}

e qui ci sono i miei altri 2 oggetti che ereditano la classe base (MoodyObject):

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

namespace ConsoleApplication1
{
    public class SadObject: MoodyObject
    {
        protected String getMood()
        {
            return "sad";
        }

        //specialization
        public void cry()
        {
            Console.WriteLine("wah...boohoo");
        }
    }
}

E

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

namespace ConsoleApplication1
{
    public class HappyObject: MoodyObject
    {
        protected String getMood()
        {
            return "happy";
        }

        public void laugh()
        {
            Console.WriteLine("hehehehehehe.");
        }
    }
}

ed ecco il mio principale:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MoodyObject moodyObject = new MoodyObject();
            SadObject sadObject = new SadObject();
            HappyObject happyObject = new HappyObject();

            Console.WriteLine("How does the moody object feel today?");
            moodyObject.queryMood();
            Console.WriteLine("");
            Console.WriteLine("How does the sad object feel today?");
            sadObject.queryMood();
            sadObject.cry();
            Console.WriteLine("");
            Console.WriteLine("How does the happy object feel today?");
            happyObject.queryMood();
            happyObject.laugh();
        }
    }
}

Come puoi vedere, cose piuttosto semplici, ma ecco l'output:

  

Come si sente l'oggetto lunatico oggi?   Oggi mi sento lunatico!

     

Come si sente l'oggetto triste oggi? io   sento lunatico oggi! wah ... boohoo

     

Come si sente l'oggetto felice oggi?   Oggi mi sento lunatico! hehehehehehe.   Premere un tasto qualsiasi per continuare . . .

Non come mi aspettavo. Ho provato a rendere virtuale il metodo di base e chiamando override quando provo a sovrascriverlo e questo mi dà questo errore " impossibile sovrascrivere il membro ereditato 'MoodyObject.getMood ()' perché non è contrassegnato come virtuale, astratto o override " . Ho anche provato senza il virtuale e l'override e pensa che sto cercando di nascondere il metodo di base. Ancora una volta, sono nuovo di OOP e apprezzerei qualsiasi consiglio.

MODIFICATO PER AGGIUNGERLO: l'ho trovato! Il MoodyObject.cs era solo un "oggetto soluzione" nell'esploratore della soluzione rispetto a una "ConsoleApplication1" articolo. L'ho trascinato fino al punto in cui apparteneva all'esploratore della soluzione e voilà! Ora funziona. Ho indicato la risposta di Luc come risposta perché mi ha offerto l'aiuto di cui avevo bisogno per arrivare a dove l'ho risolto ... Sto imparando così tanto qui. È incredibile e voi ragazzi e ragazze siete pazzi intelligenti!

È stato utile?

Soluzione

In C # i metodi non sono virtuali per impostazione predefinita, quindi se si progetta un metodo come sovrascrivibile, è necessario specificarlo come virtuale:

class Base 
{
  protected virtual string GetMood() {...}
}

In secondo luogo, è necessario specificare che si sovrascriverà il metodo dalla classe base nella classe derivata.

class Derived : Base
{
  protected override string GetMood() {...}
}

Se non specifichi " sovrascrivi " parola chiave, otterrai un metodo che nasconde il tipo di base (e un avviso dal compilatore per inserire la parola chiave "nuova" per il metodo per dichiararlo esplicitamente).

Se si desidera interrompere la catena di ereditarietà e impedire ulteriori sostituzioni del metodo, è necessario contrassegnare il metodo come sigillato, in questo modo:

  protected sealed override string GetMood() {...}

Altri suggerimenti

Devi usare la parola chiave override per sovrascrivere qualsiasi virtuale o implementare qualsiasi metodo astratto.

public class MoodyObject
{
    protected virtual String getMood() 
    { 
        return "moody"; 
    }    
    public void queryMood() 
    { 
        Console.WriteLine("I feel " + getMood() + " today!"); 
    }
}

public class HappyObject : MoodyObject
{
    protected override string getMood()
    {
        return "happy";
    }
}

Quello che consiglierei qui è che probabilmente intendevi che MoodyObject fosse una classe astratta. (Dovresti cambiare il tuo metodo principale se lo fai, ma dovresti esplorarlo) Ha davvero senso essere in una modalità lunatica? Il problema con quello che abbiamo sopra è che il tuo HappyObject non è tenuto a fornire un'implementazione per getMood. Facendo un abstract di classe fa diverse cose:

  1. Non è possibile rinnovare un'istanza di una classe astratta. Devi usare una classe per bambini.
  2. Puoi forzare i bambini derivati ??ad implementare determinati metodi.

Quindi per fare ciò finisci:

public abstract class MoodyObject
{
    protected abstract String getMood();

    public void queryMood() 
    { 
        Console.WriteLine("I feel " + getMood() + " today!"); 
    }
}

Nota come non fornisci più un'implementazione per getMood.

Per quanto ne so, in Java tutti i metodi sono virtuali per impostazione predefinita. Questo non è il caso di C #, quindi è necessario contrassegnare i metodi della classe base con " virtual " ;, ad es. stringa virtuale protetta getMood () ... e le sostituzioni con " override " ;, ad es. stringa di override protetta getMood () ... .

Se si desidera sovrascrivere un metodo di classe base, deve essere dichiarato come virtual . Il metodo di override in una classe derivata deve essere esplicitamente dichiarato come override . Questo dovrebbe funzionare:

public class BaseObject
{
    protected virtual String getMood()
    {
        return "Base mood";
    }

    //...
}

public class DerivedObject: BaseObject
{
    protected override String getMood()
    {
        return "Derived mood";
    }
    //...
}

Modifica: l'ho appena provato in un'applicazione console c # e si compila. Quindi il codice sorgente che usi dovrebbe differire in alcuni pezzi piccoli ma importanti da quello che hai pubblicato qui.

Il mio programma.cs è questo:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {    
            // leaving out your implementation to save space...    
        }
    }    

    public class SadObject : MoodyObject
    {
        protected override String getMood()
        {
            return "sad";
        }

        //specialization
        public void cry()
        {
            Console.WriteLine("wah...boohoo");
        }
    }

    public class HappyObject : MoodyObject
    {
        protected override String getMood()
        {
            return "happy";
        }

        public void laugh()
        {
            Console.WriteLine("hehehehehehe.");
        }
    }
}

Devi dire a C # che il tuo oggetto ha la precedenza sulla funzione dalla classe base.

Ecco l'articolo MSDN sulla sintassi di cui hai bisogno: http://msdn.microsoft.com/en-us/library/ebca9ah3 (VS.71) aspx

public class SadObject: MoodyObject    
{        
    override String getMood()

Rendendo il tuo metodo GetMood virtuale in Moody e override nelle classi derivate, il tuo codice dovrebbe funzionare. Sei sicuro di aver inserito queste parole chiave a cui appartengono? Ecco il codice completo, che viene compilato ed eseguito correttamente:

public class MoodyObject
{
    protected virtual String getMood()
    {
        return "moody";
    }

    public void queryMood()
    {
        Console.WriteLine("I feel " + getMood() + " today!");
    }
}

public class SadObject : MoodyObject
{
    protected override String getMood()
    {
        return "sad";
    }

    //specialization
    public void cry()
    {
        Console.WriteLine("wah...boohoo");
    }
}

public class HappyObject : MoodyObject
{
    protected override String getMood()
    {
        return "happy";
    }

    public void laugh()
    {
        Console.WriteLine("hehehehehehe.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        MoodyObject moodyObject = new MoodyObject();
        SadObject sadObject = new SadObject();
        HappyObject happyObject = new HappyObject();

        Console.WriteLine("How does the moody object feel today?");
        moodyObject.queryMood();
        Console.WriteLine("");
        Console.WriteLine("How does the sad object feel today?");
        sadObject.queryMood();
        sadObject.cry();
        Console.WriteLine("");
        Console.WriteLine("How does the happy object feel today?");
        happyObject.queryMood();
        happyObject.laugh();

        Console.Read();
    }
}

Forse il tuo errore deriva dal fatto che in Java tutti i metodi sono virtuali, il che non è il caso è C # (come sottolineato da Dan C.).

public class SadObject: MoodyObject
    {
        override String getMood()

È necessario contrassegnare le sostituzioni di getMood con la "sostituzione" " parola chiave. Dovrai anche contrassegnare il metodo getMood di base con " virtual " parola chiave.

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