Generelles Problem mit Typ und Vererbung



  • Ich versuch es mal mit einem hoffentlich anschaulicher Beschreibung:

    Ich möchte mit meinem Prog mehrer verschiedene reale Dinge steuern, zB Fahrzeuge

    Ich hab also eine Klasse Fahrzeuge, die alle Eigenschaften defniert fahren, bremsen usw.
    Weiterhin hab ich dann für jedes Fahrzeug ne eigene Klasse zB Motorrad in der eben dann ein bestimmtes objekt gesteuert wird die eben von "Fahrzeug" abgeleitet wird. Da ja die einzeln Objekte andere befehle erwarten um eben zu fahren oder zu bremsen.

    Nun möchte ich alle Fahrzeuge in einen Array packen also hab ich mir folgendes gedacht

    Fahrzeug[] fahrzeug = new Fahrzeug[3];
    fahrzeug[0] = new Motorrad();
    fahrzeug[1] = new Auto();
    fahrzeug[2] = new Schiff();
    

    und möchte dann auf die einzelen Elemente so zugreifen als wären sie "Fahrzeug", sprich

    fahrzeug[i].GasGeben();
    

    nun meckert das Prog na kalr schon am Anfang beim initialisieren des Arrays:
    "'System.InvalidCastException' " ok, ist mir klar, das geht halt wohl nicht so.

    Aber wie kann ich es dann machen. Da der einzele Typ erst zur Laufzeit bekannt ist, und es eben unterschiedliche Typen gleichzeitig gibt.

    Ich hoffe Ihr könnt mich verstehen



  • Nur dass ich das richtig verstehe: Die Klassen Motorrad, Auto, Schiff sind jeweils von Fahrzeug abgeleitet, oder?



  • Hi.

    Das ist eigentlich nicht schwer.
    Du brauchst eine virtuelle Methode in deiner Basisklasse, die von den Abgeleiteten Klassen überschrieben wird.

    Auf Dein Beispiel angewendet sieht das dann so aus:

    //fahrzeug.cs
    public virtual void GasGeben()
    {
    	Console.WriteLine("Klasse Fahrzeug");
    }
    //auto.cs
    public override void GasGeben()
    {
    	Console.WriteLine("Klasse Auto");
    }
    

    Die Liste:

    Fahrzeug[] fahrzeug = new Fahrzeug[2];
    fahrzeug[0] = new Fahrzeug();
    fahrzeug[1] = new Auto();
    
    fahrzeug[0].GasGeben();
    fahrzeug[1].GasGeben();
    

    Die Ausgabe sieht dann so aus:

    Klasse Fahrzeug
    Klasse Auto

    Bei dem Aufruf 'fahrzeug[1].GasGeben();' wird die überschriebene Methode von Auto verwendet.

    Ist die Methode in der Klasse Auto nicht vorhanden, oder nicht als 'override' gekennzeichnet wird die Methode GasGeben von der Oberklasse Fahrzeug benutzt.

    GuenniAtWork



  • 1. Ja sie sind alle abgeleitet.

    2. Ich hab die Methoden abstract gemacht, das ist auch nicht das Prob, das Prob ist eben der Array. Und ich möchte eigentlich nicht nen object-Array oder so machen, es müsste doch irgendwie auch so gehen, denk ich mal



  • Schrieb Guenni nicht gerade dass es das genau so tut? 😉

    Funktioniert wirklich, auch wenn man virtual durch abstract ersetzt!

    EDIT: Hier noch der vollständige Programmcode, der eben noch in meinem VS2005 funktionierte 😉

    namespace ConsoleApplication1
    {
        abstract class Fahrzeug 
        {
            public abstract void GasGeben();
        }
    
        class Motorrad : Fahrzeug
        {
            public override void GasGeben() { Console.WriteLine("Motorrad gibt Gas!"); }
        }
    
        class Auto : Fahrzeug
        {
            public override void GasGeben() { Console.WriteLine("Auto gibt Gas!"); }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Fahrzeug[] ary = new Fahrzeug[2];
                ary[0] = new Motorrad();
                ary[1] = new Auto();
    
                ary[0].GasGeben();
                ary[1].GasGeben();
    
                Console.ReadLine();
            }
        }
    }
    


  • Hmm ja funktioniert wenn ich die Konstruktoren entferne. Dann liegt da wohl mein.

    Aber warum?

    Was muss ich dabei beachten. meine konstruktoren sehen in etwa so aus:

    abstract class Fahrzeug
        {
            protected int a;
            protected int b;
    
            public Fahrzeug( int a, int b ){
                this.a = a;
                this.b = b;
            }
    
            public Fahrzeug(){};
    
            public abstract void GasGeben();
        }
    
        class Motorrad : Fahrzeug
        {
            public Motorrad( int a, int b ){
                this.a = a;
                this.b = b;
            }
    
            public override void GasGeben() { Console.WriteLine("Motorrad gibt Gas!"); }
        }
    
        class Auto : Fahrzeug
        {
            public Auto( int a, int b ){
                this.a = a;
                this.b = b;
            }
    
            public override void GasGeben() { Console.WriteLine("Auto gibt Gas!"); }
        }
    

    Ich mach jetzt die Arbeit vom Konstruktor einfach extra, und lass Ihn weg, und schon geht´s 😉

    Sollet jemand eine "schönere" Lösung haben kann er sie ja hier posten



  • Das Funktioniert schon mit deinen Konstruktoren!
    Du musst halt beim erzeugen der Objekte die Werte angeben.

    Fahrzeug[] fahrzeug = new Fahrzeug[2];
    fahrzeug[0] = new Auto(1,2);
    fahrzeug[1] = new Motorrad(1,2);
    
    fahrzeug[0].GasGeben();
    fahrzeug[1].GasGeben();
    

    In c++ gab es noch die folgende Möglichkeit

    AbgeleiteteklasseKonstruktor(int ElementBasis, int ElementAbgeleitet):BasisklasseKonstruktor(ElementBasis)
    {
        this->ElementAbgeleitet = ElementAbgeleitet;
    }
    

    Dabei wird der Attributwert des in der Basisklasse deklarierten Attributes an den Basisklassenkonstuktor weitergegeben. Man braucht nur noch den Attributwert der abgeleiteten Klasse zu handeln.

    Ob das auch in C# geht weiß ich nicht.(Wär aber mal ganz interesannt.)

    GuenniAtWork



  • Ja, das geht in C# natürlich auch 😉 Die Syntax gefällt mir sogar besser, weil man den Basisklassennamen nur ein einziges Mal beim Ableiten braucht:

    AbgeleiteteKlasseCtor(int a, int b) : base(a)
    {
        this.b = b;
    }
    


  • Jup.
    habs mal bei Google eingetippt.
    Wollte ich grad posten. 😃

    Aber danke.

    GuenniAtWork



  • Jep, jetzt ist´s fein und macht wieder Spass 😃


Anmelden zum Antworten