Autor Beitrag
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4433
Erhaltene Danke: 908


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 07.03.17 15:15 
Globale Variablen habe so einen nicht objektoriebtierten Klang und waren auch schon vorher eher ein Zeichen von schlechter Programmierung. Deshalb würde ich es nicht so nennen. Letztlich hängen ja an Klassen/Methoden/Properties/feldern etc. noch Sichtbarkeiten (public, private etc.). Bei Leuten die globalen Variablen ~denken~ spielt solche Dinge meist keine Rolle und führen dann zu schlechtem Code. Aus Anfängersicht kann man es aber so sehen das etwas statisches leichter zu erreichen ist als etwas das an einer Instanz hängt. Es ist etwas ~globaler~ ja. Diese Sichtweise wird aber ab einer bestimmten Projektgröße problematisch.

Für diesen Beitrag haben gedankt: Delphi-Laie
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1586
Erhaltene Danke: 231


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Di 07.03.17 15:24 
user profile iconDingo hat folgendes geschrieben Zum zitierten Posting springen:
Also das "using" nutzt man dann sozusagen auf Deutsch aus Gründen der "Faulheit"?!


Damit werden Bibliotheken eingebunden, also modulare Programmierung ermöglicht.

Mit Faulheit allein hat das kaum noch etwas zu tun. Zum einen kann man nicht ständig das Rad neu erfinden, die Zeit hat man nicht, es ist auch unproduktiv. Zum anderen, wenn man wirklich versuchen wollte, die Funktionalität nachzubilden oder gar aus dem Quellext der Bibliothek zu "borgen" (also zu kopieren, was eigentlich nicht erlaubt ist), wird man kaum erfolgreich sein, weil es zuviele Abhängigkeiten untereinander gibt. Irgendwann hat man den Großteil des Modules in sein eigenes Projekt übernommen und eingebunden, und das ist soviel, daß der eigene Quelltext völlig darin intergeht.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4433
Erhaltene Danke: 908


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 07.03.17 15:33 
Zitat:
Damit werden Bibliotheken eingebunden, also modulare Programmierung ermöglicht.


Nicht in c#/.Net. Referenzieren einer Bibliothek macht man über einen anderen Weg. Im Gegensatz zu anderen Sprachen ist ein Namespace auch nicht direkt gleichzusetzen mit einer Assembly/Package/Bibliothek und (ein solcher) using bezieht sich nur auf Namespaces. Mit der "Faulheit" hat er also nicht ganz unrecht. Netter kann man auch sagen das es es die Lesbarkeit erhöht. Immer den vollqualifizierten Namen einer Klasse zu benutzen macht Code schwer lesbar.

Für diesen Beitrag haben gedankt: Delphi-Laie
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1586
Erhaltene Danke: 231


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Di 07.03.17 21:51 
Nun, für mich war "using" analog zu "uses", zumal Borland-Guru Anders Hejlsberg ja auch C# mehr oder weniger aus der Taufe hob.

Anscheinend ist es eher mit dem Pascal-Schlüsslwort "with" gleichzusetzen. Dann stimme ich zu, daß es dem Einsparen von Tipparbeit dient (wobei ich with grundsätzlich nicht verwende).
Dingo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 64
Erhaltene Danke: 1



BeitragVerfasst: Mi 08.03.17 14:54 
Freut mich, dassa hier so geholfen wird! :)

Kommen wir mal zu Konstruktormethoden, ist in meinem Buch etwas verwirrend beschrieben, mal sehen ob ich es richtig verstanden habe, nehmen wir mal folgenden Quellcode:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Lektion3
{
    // Die Basisklasse für die Flugzeuge, auch generelle Klasse genannt
    class Luftfahrzeug {
        // Variablendeklaration
        public string kennung;

        // Konstruktormethode 1, OHNE Parameter:
        public Luftfahrzeug(){
        }

        // Konstruktormethode 2, MIT Parameter:
        public Luftfahrzeug(string kennung){
            this.kennung = kennung;
        }

        // Methodendeklaration
        public void Steigen(int meter){
            Console.WriteLine(kennung + " steigt " + meter + " Meter");
            Console.ReadLine();
        }

        public void Sinken(int meter){
            Console.WriteLine(kennung + " steigt " + meter + " Meter");
            Console.ReadLine();
        }

    }
    
    // Flugzeug, eine Unter-Klasse von Luftfahrzeuge
    class Flugzeug : Luftfahrzeug{

        public Flugzeug(){
        }
    }



    class Program
    {
        static void Main(string[] args)
        {
            // Ruft Konstruktormethode MIT Parameter auf
            Luftfahrzeug flieger = new Luftfahrzeug("LH 4080");
            flieger.Steigen(100);
            flieger.Sinken(50);

            // Ruft Konstruktormethode OHNE Parameter auf
            Flugzeug flieger2 = new Flugzeug();
            flieger2.Steigen(333);
        }
    }
}


So, in der Basisklasse sind zwei Konstruktormethoden, eines mit Argument, eines ohne Argument.

Nun habe ich zwei Flugzeuge, eines welches über die Klasse Luftfahrzeuge als Objket definiert wurde und ein Flugzeug welches über Flugzeug als Objekt definiert wurde.

Wenn ich in der Klasse class Flugzeug : Luftfahrzeug{} habe, die KEINE Konstruktormethode hat, wird, so hab ich es verstanden ja automatisch die Konstruktormethode der Basisklasse angesprochen.

Das selbe wenn ich in der Konstruktormethode einen Parameker habe. Wenn ich in class Flugzeug : Luftfahrzeug{} keine Konstruktormethode mit einem Parameter habe, wird autoamatisch zur Basisklasse gegangen und da eine Konstruktormethode gesucht, zu der mein Parameter passt.

Nun steht in meinem Buch zu diesem Beuspiel:

ausblenden C#-Quelltext
1:
2:
3:
class Flugzeug : Luftfahrzeug{
     public Flugzeug(){
}


Zitat: Diese Konstruktormethode tut nichts, ihr Aufruf hat daher keine weitre Folgen als den Aufruf der Konstruktormethode der Basisklasse. Sie können aber im Konstruktor-Programmblock durchaus Anweisungen schreiben. In Frage käme z.B. die Festlegung, dass die Varaible „kennung“ (Klasse Luftfahrzeuge“) initialisiert wird:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
class Flugzeug : Luftfahrzeug 
     {
     class Flugzeug()
     {
          kennung = „keine Kennung“;
     }
}


So viel bis hier her und nun bin ich etwas ratlos.

Es ist schon klar, dass wenn ich in meiner Klasse class Flugzeug : Luftfahrzeug keine Konstruktormethode habe, automatisch die der Basisklasse genutzt wird, jedoch: Warum wird die Baisklassenkonstruktormethode auch aufgerufen, wenn ich doch schon eine Konstruktormethode in class Flugzeug : Luftfahrzeug habe, oder versteh ich da was falsch?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4433
Erhaltene Danke: 908


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 08.03.17 15:29 
Zitat:
Warum wird die Baisklassenkonstruktormethode auch aufgerufen, wenn ich doch schon eine Konstruktormethode in class Flugzeug : Luftfahrzeug habe, oder versteh ich da was falsch?


Da kommt das mit den Sichtbarkeiten ein wenig ins Spiel. Jedes Mitglied einer Klasse (egal ob Feld,Property,Methode) Klasse hat eine eigene Sichtbarkeit und die gilt auch zwischen Ableitungen. Wenn also die Klasse Luftfahrzeug private Mitglieder hätte die initialisiert werden müßten kann man das nicht direkt von Flugzeug aus erledigen es muß von Luftfahrzeug aus passieren.

Nemmen wir uns dein Beispiel und stellen uns vor das das Feld kennung in der Luftfahrzeug Klasse privat wäre (das wäre eh richtiger und kannst du auch am besten selbst probieren) dann wirst du feststellen das die Lösung kennung im Konstruktor von Flugzeug zu setzen nicht mehr funktioniert. Das wäre auch im allgemeinen besser. Es gibt dann weniger stellen von wo aus kennung geändert werden kann das führt zu weniger Abhängigkeiten die zu leichter handhabbaren Code führen (das nur so, mußt du jetzt nicht nachvollziehen können das kommt später mit etwas Erfahrung).

Wie sollte man also kennung setzen? Nun die Luftfahrzeug Klasse hat dafür bereits einen Konstruktor den man aufrufen sollte der das kann. Du hast bereits bemerkt das der parameterlose Konstruktor aufgerufen wird und du das nicht verhindern kannst. Was du aber kannst ist steuern welcher Konstruktor benutzt wird. Es ist also so das immer einer Konstruktor benutzt wird in jeder Klasse deiner Vererbungshierarchie um zu erzwingen das alles richtig initialisiert wird du hast aber Einfluß welche Konstruktoren aufgerufen werden. Dazu gibt es die Schlüsselwort base das man an den Konstruktor hängt.

Also anstatt so

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
class Flugzeug : Luftfahrzeug 
{
    public Flugzeug() // Hier wird implizit auch der parameterlose Konstruktor von Luftfahrzeug aufgerufen. Der parameterlose Konstruktor wird immer benutzt wenn man keinen anderen benennt.
    {
        kennung = "keine Kennung";
    }
}

solle man dann
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
class Flugzeug : Luftfahrzeug 
{
    public Flugzeug() : base("keine Kennung")
    {}
}


benutzten. Base bezeichnet die Konstruktoren der Vorfahrklasse und da hier ein string übergeben wird also der Konstruktor mit dem string Parameter in der Vorgfahrklasse aufgerufen anstatt den parameterlosen,

Für diesen Beitrag haben gedankt: Dingo
Dingo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 64
Erhaltene Danke: 1



BeitragVerfasst: Mi 08.03.17 15:48 
Verstehe, was ist aber wenn ich nun die Klasse Düsenflugzeuge nehme.

Ich initialisiere nun mal ein Düsenflugzeug:

ausblenden C#-Quelltext
1:
2:
Düsenflugzeuge flieger4 = new Düsenflugzeuge("LH 999");
flieger4.Steigen(999);


Demzufolge würde nun dieser Konstruktor aufgerufen:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
class Düsenflugzeuge : Flugzeug{
     // Konstruktormethode
     public Düsenflugzeuge(string kennung) : base(kennung){
     }
}


Der Konstruktor, was macht er?

Du schriebst, er würde nun wieder die nächst höhere Klasse ansprechen? Also dann diese:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
class Flugzeug : Luftfahrzeug{

     // Konstruktormethode OHNEParamete      
     public Flugzeug(){
     }

     // Konstruktormethode MIT Parameter
     public Flugzeug(string kennung) : base(kennung){
     }
}


Diese wiederrum wird nun Luftfahrzeuge ansprechen?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4433
Erhaltene Danke: 908


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 08.03.17 15:57 
Zitat:
Diese wiederrum wird nun Luftfahrzeuge ansprechen?


Genau. Man kann keine Ebene überspringen, also von Düsenflugzeuge aus direkt den Konstruktor von Luftfahrzeug zu benutzten ist nicht erlaubt. Auf jeder Vererbungsebene muß mindestens 1 Konstruktor benutz werden.
Dingo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 64
Erhaltene Danke: 1



BeitragVerfasst: Mi 08.03.17 16:03 
Ah, langsam versteh ichs. Also wird damit:

ausblenden C#-Quelltext
1:
2:
public Düsenflugzeuge(string kennung) : base(kennung){
}


Noch genauer gesagt damit:

ausblenden C#-Quelltext
1:
base(kennung)					


So lange die Methodendeklaration weiter in der Klassenhirarchie nach oben gereicht, bis de Variable string kennung gefunden wird und die Methodendeklaration ausgefhrt werden kann?

Bedeutet also, so lange die Variable die ich verwenden möchte in der nächst höheren Ebene ist, muss ich : base nutzen?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4433
Erhaltene Danke: 908


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 08.03.17 19:14 
user profile iconDingo hat folgendes geschrieben Zum zitierten Posting springen:

ausblenden C#-Quelltext
1:
base(kennung)					


So lange die Methodendeklaration weiter in der Klassenhirarchie nach oben gereicht, bis de Variable string kennung gefunden wird und die Methodendeklaration ausgefhrt werden kann?



Nein. base heißt Vorfahr und aus dem übergebenen Type, hier string, weiß der Compiler dann das er im Vorfahren den Konstruktor mit einem string aufzurufen hat. Wenn es einen solchen nicht gibt wirst du bei einem Compiliervorgang eine entsprechende Fehlermeldung bekommen. Er wird nicht weitersuchen zum Beispiel im Vor-Vorfahren ob es dort einen solchen Konstruktor gibt. Dann wären wir ja wieder an dem Punkt das eine Ebene ausgelassen wird beim Konstruktorenaufruf udn esmuß für jede Klasse in der Vererbungshierarchie ein Konstruktor benutzt werden.

Zitat:
Bedeutet also, so lange die Variable die ich verwenden möchte in der nächst höheren Ebene ist, muss ich : base nutzen?


Jein es geht um die Konstruktoren nicht Variablen. Wenn der entsprechende Konstruktor die Variable setzt dann ist das das gleiche aber da gibt es ja keinen Zwang es so programmiert zu haben.

Für diesen Beitrag haben gedankt: Dingo
Dingo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 64
Erhaltene Danke: 1



BeitragVerfasst: Do 09.03.17 09:32 
OK, dann noch mal ne Frage dazu:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Lektion3
{
    class Luftfahrzeug
    {
        public string kennung;
        public string test;

        // Konstruktormethode 1:
        public Luftfahrzeug(){
            Console.WriteLine("Basisiklasse");
        }

        // Konstruktormethode 2:
        public Luftfahrzeug(string kennung, string test){
            this.kennung = kennung;
            this.test = test;
           }
    }

    class Flugzeuge : Luftfahrzeug{
        public Flugzeuge(){
            Console.WriteLine("Subklasse");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Ruft Konstruktormethode MIT Parameter auf
            Flugzeuge flieger = new Flugzeuge();
            Console.WriteLine(flieger.kennung + flieger.test);
            Console.ReadLine();

        }
    }
}


In diesem Beispiel habe ich mal die Erzeugung eines Objektes ohne Parameter probiert. Es wird über die Klasse Flugzeuge aufgerufen. Nun meine Frage wäre, warum startet in der Basisklasse ebenfalls der Konstruktor ohne Methode und nicht nur der in der Subklasse? Hat dies eine spezielle Bewandtnis, warum starten beide und gilt dies bei Parametern auch, wenn sowohl Basis- als auch Subklasse nur einen String als Parameter haben?

Der Output sehe ja dann so aus:

Basisklasse
Subklasse
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4059
Erhaltene Danke: 842

Win7
C++, C# (VS 2015/17)
BeitragVerfasst: Do 09.03.17 10:02 
Mir scheint, du hast das Prinzip doch noch nicht so ganz verstanden.
Es wird explizit oder implizit immer ein Basis-Konstruktor aufgerufen, und zwar immer genau der, welcher die passende Signatur (d.h. die passenden Parameter) hat.

In deinem Beispiel erzeugt der Compiler eigentlich folgenden Konstruktor, weil du explizit keinen Basisklassenkonstruktor aufgerufen hast:
ausblenden C#-Quelltext
1:
2:
3:
4:
public Flugzeuge() : base()
{
    Console.WriteLine("Subklasse");
}

Es wird also der Basisklassen-Konstruktor Luftfahrzeug() aufgerufen. Diesen - ohne Parameter - nennt man auch Standardkonstruktor (default constructor).
Es gibt nämlich noch den Fall, daß man selbst gar keinen Konstruktor bei einer Klasse definiert hat - und dann erzeugt der Compiler automatisch einen öffentlichen Standardkonstruktor dafür (weil sonst könnte man gar kein Objekt dieser Klasse erzeugen).

Und jetzt lese am besten noch mal die Antworten von user profile iconRalf Jansen durch.
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 09.03.17 10:15 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4433
Erhaltene Danke: 908


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 09.03.17 10:51 
Zitat:
Schade, das Clowns Beispiel war doch nicht zielführend. Hätte man es noch einfacher machen können?


Auch bei Codebeispielen gilt es gibt kein "One size fits all". Einfacheres Beispiel also möglicherweise aber eben leider nicht passend für jeden.
OlafSt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 459
Erhaltene Danke: 90

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Do 09.03.17 10:57 
Ihr alle verschweigt die Geheimnisse ;)

Nehmen wir eine einfachst-Klasse:
ausblenden C#-Quelltext
1:
2:
3:
4:
public class Auto
{
   public void Starten() { }
}


Diese Klasse hat nur eine Methode, Starten genannt. Keine Properties, keine Konstruktoren, nix.

Wenn ich nun eine Instanz davon erstellen will, schreibe ich folgenden Code:
ausblenden C#-Quelltext
1:
   public Auto MyCar = new Auto();					


Ganz offensichtlich wird da ein Konstruktor aufgerufen - aber meine Klasse hat doch gar keinen ?!?!?

Das Geheimnis: Jede Klasse hat einen Konstruktor. Einen, der public ist (sonst wäre er nicht aufrufbar) und keine Parameter erwartet. Hat, wie in meinem Beispiel, eine Klasse keinen Konstruktor, wird klammheimlich einer von C# erzeugt. Und dann hat die Klasse einen Konstruktor und der kann und wird dann aufgerufen, wenn man eine Instanz erzeugt.

In diesem Konstruktor ist dann entsprechender Code drin, der Speicher für die Klasse reserviert, Felder anlegt usw. Dieser Code wird bei Aufruf eines jeden Konstruktors ausgeführt, auch wenn man selbst einen oder mehrere davon definiert hat. Er ist sozusagen "versteckt".

Und jetzt bekommt das ganze Sinn: Im Beispiel mit den Luftfahrzeugen und Flugzeugen wird bei
ausblenden C#-Quelltext
1:
Flugzeuge flieger = new Flugzeuge();					

logischerweise der Konstruktor von Flugzeuge aufgerufen. Da aber Flugzeuge von der Klasse Luftfahrzeuge abstammt, muß zunächst dessen Konstruktor aufgerufen werden, denn wir müssen ja erstmal Speicher für die Basisklasse besorgen, bevor wir den Rest an Speicher für die Subklasse besorgen können. Darum werden die Konstruktoren allesamt aufgerufen - auch ohne base()-Angabe.

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.

Für diesen Beitrag haben gedankt: Dingo
Dingo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 64
Erhaltene Danke: 1



BeitragVerfasst: Do 09.03.17 11:02 
Also "static" hab ich schon halbwegs verstanden, komplett verstehen werd ichs wohl erst mit genügend Übungen und die sind in meinem Lehrbuch echte Mangelware, alles sehr Trocken. Zum "base", ich dachte echt ich habs langsam und langsam werd ich immer verwirrter um so länge rich über "base" nachdenke.^^"

Zum Clown Beispiel, das liegt nicht an dir bzw. deinem Beispiel direkt, Frühlingsrolle. Etwas versteh ich es schon, aber zum Beispiel das nicht:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
Clown[] clowns = { clown1, clown2, clown3 };
msg = "";
foreach (Clown c in clowns)
{
 msg += string.Format("{0} is type of {1}\n", c.Name, c.GetType().Name);
}
MessageBox.Show(msg);


Man wird in meinem Buch recht trocken sofort in Objekte und Klassen geworfen. Was nun Typen oder primitive Typen sind, Methoden, Array und so weiter und so viel, wird zwar schon gebraucht, zumindest teilweise, steht aber erst viel weiter hinten im Heft! Demzufolge brauche ich ziemlich leichte Beispiele, dich ich mit meinem jetzigen Wissensstand lesen kann. Was z.B. foreach ist oder GetType, weiß ich leider noch nicht. Windows Forms hab ich noch gar nicht genutzt, alles läuft bisher über Konsolenanwendung.

Hab mir jetzt mal zum Verständniss ein Test-Programm zusammen geschustert, um es besser zu verstehen:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
namespace Lektion3
{
    class Luftfahrzeug
    {
        public string kennung;

        // Konstruktormethode 1:
        public Luftfahrzeug(){
            Console.WriteLine("Basisiklasse");
        }

        // Konstruktormethode 2:
        public Luftfahrzeug(string kennung){
            this.kennung = kennung;
            Console.WriteLine("Basisiklasse mit Parameter");
           }
    }

    class Flugzeuge : Luftfahrzeug{
        public Flugzeuge(){
            Console.WriteLine("Test1");
        }

        public Flugzeuge(string kennung) : base(kennung){
            Console.WriteLine("Test2");
           }
    }

    class Düsenflugzeug : Flugzeuge {
        public Düsenflugzeug(){
            Console.WriteLine("Test3");
        }

        public Düsenflugzeug(string kennung) : base(kennung){
            Console.WriteLine("Test4");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Ruft Konstruktormethode MIT Parameter auf
            Düsenflugzeug flieger = new Düsenflugzeug("Testung");
            Console.WriteLine(flieger.kennung);
            Console.ReadLine();

        }
    }
}


Was passiert?

Als Output bekomme ich:
Basisklasse mit Parameter
Test2
Test4
Testung der Kennung

Es wird also ein Objekt Flieger erzeugt, welches von der Klasse Düsenflugzeuge abstammt. Als Parameter haben wir den String "Testung der Kennung". Dieser String soll an die Variable "Kennung" übergeben werden, welche ja Mitglied der Basisklasse Luftfahrzeuge ist.

Da Flieger zur Klasse der Düsenflugzeuge gehört, wird nun aus der Basisklasse des Objektges Flieger der passende Konstruktor gesucht:

ausblenden C#-Quelltext
1:
2:
3:
public Düsenflugzeug(string kennung) : base(kennung){
     Console.WriteLine("Test4");
}


Dieser Konstruktor ruft nun wieder seine Base auf:

ausblenden C#-Quelltext
1:
2:
3:
public Flugzeuge(string kennung) : base(kennung{
     Console.WriteLine("Test2");
}


Der wiederrum ruft nun seinen Konstruktor auf:

ausblenden C#-Quelltext
1:
2:
3:
4:
public Luftfahrzeug(string kennung){
     this.kennung = kennung;
     Console.WriteLine("Basisiklasse mit Parameter");
}


Im letzten Konstruktor wird nun der Befehl nicht mehr weiter gegeben, sondern an die Basisklasse.

So, das ganze hätte man auch so schreiben können:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
namespace Lektion3
{
    class Luftfahrzeug
    {
        public string kennung;

        // Konstruktormethode 1:
        public Luftfahrzeug(){
            Console.WriteLine("Basisiklasse");
        }

        // Konstruktormethode 2:
        public Luftfahrzeug(string kennung){
            this.kennung = kennung;
            Console.WriteLine("Basisiklasse mit Parameter");
        }
    }

    class Flugzeuge : Luftfahrzeug{
            public Flugzeuge(){
            Console.WriteLine("Test1");
        }

        public Flugzeuge(string kennung){
            Console.WriteLine("Test2");
        }
    }

    class Düsenflugzeug : Flugzeuge
    {
        public Düsenflugzeug(){
            Console.WriteLine("Test3");
        }

        public Düsenflugzeug(string kennung){
            this.kennung = kennung;
            Console.WriteLine("Test4");
        }
    }

    class Program
    {
        static void Main(string[] args){
            // Ruft Konstruktormethode MIT Parameter auf
            Düsenflugzeug flieger = new Düsenflugzeug("Testung");
            Console.WriteLine(flieger.kennung);
            Console.ReadLine();

        }
    }
}


Mit

ausblenden C#-Quelltext
1:
this.kennung = kennung;					


greife ich auf die string Kennung zu und weiße ihr einen Wert zu.

Das Ergebnis sieht nun anders aus:

Basisklasse
Test1
Test4
Testung

Mal zur Erinnerung wo alles mit base geschrieben wurde:

Basisklasse mit Parameter
Test2
Test4
Testung

Der große Unterschied ist ja nun, dass im ersten Test alle Konstruktormethoden mit Parameter angesprochen wurden, im zweiten Test nur die erste Konstruktormethode mit Parameter, dann alle Konstruktormethoden ohne Parameter.

Also wird im Endeffekt, wenn wir nun mal von einen Konstruktor ohne Parameter ausgehen, immer der Konstruktor der darvor war mit angesprochen, mit man zur obersten Basisklasse kommt, den Standardkonstruktor.

EDIT:

user profile iconOlafSt hat folgendes geschrieben Zum zitierten Posting springen:
Und jetzt bekommt das ganze Sinn: Im Beispiel mit den Luftfahrzeugen und Flugzeugen wird bei
ausblenden C#-Quelltext
1:
Flugzeuge flieger = new Flugzeuge();					

logischerweise der Konstruktor von Flugzeuge aufgerufen. Da aber Flugzeuge von der Klasse Luftfahrzeuge abstammt, muß zunächst dessen Konstruktor aufgerufen werden, denn wir müssen ja erstmal Speicher für die Basisklasse besorgen, bevor wir den Rest an Speicher für die Subklasse besorgen können. Darum werden die Konstruktoren allesamt aufgerufen - auch ohne base()-Angabe.


Das wusste ich, es gibt einen unsichtbaren Konstruktor der immer da ist. Also wird der Speicherplatz für mein neues Objekt im Endeffekt nicht von meinem Konstruktor an sich reserviert, sondern dies macht dann der oberste Konstruktor, der Standardkonstruktor und deshalb werden alle Zwischen-Konstruktor aufgerufen, weil der Standardkonstruktor demnach der Ausgangspunkt wäre?
Über meine anderen Konstruktoren gebe ich ihm dann nur den Befehl?

Man könnte also sagen mit "base" lenke ich den Konstruktor in eine bestimmte Richtung?

EDIT 2:

Langsam wirds her Wirt:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
namespace Lektion3
{
    class Luftfahrzeug
    {
        public string kennung;

        // Konstruktormethode 1:
        public Luftfahrzeug(){
            Console.WriteLine("Basisiklasse");
        }

        // Konstruktormethode 2:
        public Luftfahrzeug(string kennung){
            this.kennung = kennung;
            Console.WriteLine("Basisiklasse mit Parameter");
        }
    }

    class Flugzeuge : Luftfahrzeug{
            public string test;
            public Flugzeuge(){
            Console.WriteLine("Test1");
        }

        public Flugzeuge(string kennung){
            Console.WriteLine("Test2");
        }

        public Flugzeuge(string FLP1, string FLP2){
            test = FLP1;
            kennung = FLP2;
            Console.WriteLine(test + kennung);
        }

    }

    class Düsenflugzeug : Flugzeuge
    {
        public Düsenflugzeug(){
            Console.WriteLine("Test3");
        }

        public Düsenflugzeug(string kennung){
            this.kennung = kennung;
            Console.WriteLine("Test4");
        }

        public Düsenflugzeug(string FLP1, string FLP2) : base(FLP1, FLP2)
        {
            Console.WriteLine("Test5");
        }
    }

    class Program
    {
        static void Main(string[] args){
            // Ruft Konstruktormethode MIT Parameter auf
            Düsenflugzeug flieger = new Düsenflugzeug("FlugzeugParameter1""FlugzeugParameter2");
            //Console.WriteLine(flieger.kennung);
            Console.ReadLine();

        }
    }
}


Hab nun mal den Spaß mit zwei Parametern auf unterschiedlichen Klassenebenen gemacht.

Aufgerufen würde also zuerst das werden:

ausblenden C#-Quelltext
1:
2:
3:
public Düsenflugzeug(string FLP1, string FLP2) : base(FLP1, FLP2){
            Console.WriteLine("Test5");
}


Was wiederrum die Basisklasse aufrufen würde:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
public Flugzeuge(string FLP1, string FLP2){
     test = FLP1;
     kennung = FLP2;
     Console.WriteLine(test + kennung);
}


Es würde nun also der Zugriff auf die Variable test und kennung erfolgen und diese würden per Konsole ausgegeben.

Es würde nun angezeigt:

Basisklasse
FlugzeugParameter1FlugzeugParameter2
Test5

Schreiben häte man es wieder auch gleich wieder so:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
public Düsenflugzeug(string FLP1, string FLP2){
     test = FLP1;
     kennung = FLP2;
     Console.WriteLine("Test5");
}
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 09.03.17 12:20 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Dingo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 64
Erhaltene Danke: 1



BeitragVerfasst: Do 09.03.17 12:24 
Da ich schon wieder net mal weiß was get, virtual und override ist und wie man es anwendet, kann ich es wieder mal nur halb verstehn.

Mal abgesehen davon, sowohl Luftfahrzeuge als auch Flugzeuge haben die selbte Variable die als Privat deklariert ist, je mit einem anderen Wert.
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 09.03.17 12:39 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Dingo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 64
Erhaltene Danke: 1



BeitragVerfasst: Do 09.03.17 12:52 
Es muss doch auch ohne virtal und override zu erklären sein. Hab so schon Probleme das zu verstehen und nun kommt noch mehr dazu um nur Konstruktormethoden zu verstehen.^^"

Lieg ich denn so dermaßen daneben mit meinen Verstädniss?

Was sagt MSDN dazu:

Zitat:
Mit dem base-Schlüsselwort kann innerhalb einer abgeleiteten Klasse auf Member der Basisklasse zugegriffen werden:

- Rufen Sie eine Methode der Basisklasse auf, die durch eine andere Methode überschrieben wurde.

- Geben Sie an, welcher Konstruktor der Basisklasse beim Erstellen von Instanzen der abgeleiteten Klasse aufgerufen werden soll.

Die Basisklasse, auf die zugegriffen wird, ist die in der Klassendeklaration angegebene Basisklasse. Wenn Sie z. B. class ClassB : ClassA angeben, wird auf die Member von ClassA aus ClassB zugegriffen, unabhängig von der Basisklasse von ClassA.


Das hab ich auch verstanden.

In meinem Buch steht:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
public Flugzeug : Luftfahrzeug{
     public Flugzeug(){
          kennung = "keine Kennung";
     }
}

Wäre das selbe wie:
ausblenden C#-Quelltext
1:
2:
public Flugzeug(string kennung) : base(kennung){
}

Eben nur eine andere Schreibweise.

Nahmen wir uns nun noch einmal das vor:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
namespace Lektion3
{
    class Luftfahrzeug
    {
        public string kennung;

        // Konstruktormethode 1:
        public Luftfahrzeug(){
            Console.WriteLine("Basisiklasse");
        }

        // Konstruktormethode 2:
        public Luftfahrzeug(string kennung){
            this.kennung = kennung;
            Console.WriteLine("Basisiklasse mit Parameter");
        }
    }

    class Flugzeuge : Luftfahrzeug{
        public string test;

        public Flugzeuge(){
            Console.WriteLine("Test1");
        }

        public Flugzeuge(string kennung){
            Console.WriteLine("Test2");
        }

        public Flugzeuge(string FLP1, string FLP2){
            test = FLP1;
            kennung = FLP2;
            Console.WriteLine(test + kennung);
        }

    }

    class Düsenflugzeug : Flugzeuge
    {
        public Düsenflugzeug(){
            Console.WriteLine("Test3");
        }

        public Düsenflugzeug(string kennung){
            this.kennung = kennung;
            Console.WriteLine("Test4");
        }

        public Düsenflugzeug(string FLP1, string FLP2){
            test = FLP1;
            kennung = FLP2;
            Console.WriteLine(test + kennung);
            Console.WriteLine("Test5");
        }
    }

    class Program
    {
        static void Main(string[] args){
            // Ruft Konstruktormethode MIT Parameter auf
            Düsenflugzeug flieger = new Düsenflugzeug("FlugzeugParameter1""FlugzeugParameter2");
            //Console.WriteLine(flieger.kennung);
            Console.ReadLine();

        }
    }
}


Wo wäre hier nun der Fehler, rein Fehler bringt er mir nicht.

Ich löse den Konstruktor aus:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
public Düsenflugzeug(string FLP1, string FLP2){
    test = FLP1;
    kennung = FLP2;
    Console.WriteLine(test + kennung);
    Console.WriteLine("Test5");
}

Wäre dies falsch, da der Member test eigentlich zu Flugzeuge gehört und kennung zu Luftfahrzeug?

Moderiert von user profile iconTh69: C#-Tags hinzugefügt


Zuletzt bearbeitet von Dingo am Do 09.03.17 13:07, insgesamt 1-mal bearbeitet