# main()-Konstruktor überschreiben / überladen



## Mesqualito (15. Nov 2008)

Habe mir Alexander Niemanns "Objektorientierte Programmierung in Java" vorgeknöpft.

Die Anleitung:

Ich habe die Klasse 'Auto'.
In der "Standard-Methode" main() wird eine Variable festgesetzt:

```
public static int anzAutos = 0;
```

Die main()-Methode (der Standard-Konstruktor) soll überschrieben werden.
Ganz klar, mit dem Name des Konstruktors = Name der Klasse.

Da steht nun drin:

```
public Auto()
{
    anzAutos++
}
```

Auch gut: es wird, da Überschreibung, beim Aufruf der Methode 'Auto()' in einer Instanz nun nicht mehr main() (also 'public static int anzAutos = 0') aufgerufen, sondern 'anzAutos++'.

Jetzt gibt es aber noch die Überladung:


```
public Auto(String kBez, short kGeschw, short kPlaetze)
{
    // Definition der o.g. Variablen
   anzAutos++;
}
```


Meine Verständnisprobleme:

1.) Ist die zweite Definition nun eine Überladung UND Überschreibung? Wo liegt der Unterschied?

2.) Wieso wird beim Aufruf des Konstruktors 'Auto(var1, (short)var2, (short)var3)' aus einer Instanz heraus nicht sowohl die erste Definition (Überschreibung) als auch die zweite Definition (Überschreibung/Überladung) aufgerufen?

2.) Würde 'anzAutos' wieder überschrieben werden, wenn das 'public static int anzAutos = 0;' in der main()-Methode in der Code-Reihenfolge nach der Überschreibung/Überladung des Konstruktors 'Auto()' bzw. 'Auto(var1, (short)var2, (short)var3)' stehen würde?

Eventuell hat jemand mal ein Beispiel, bei dem mir das "Nu' ist's sonnenklar !!" - Erlebnis beschieden wird...
Jaja, jeder fängt mal klein an


----------



## Ark (15. Nov 2008)

Mesqualito hat gesagt.:
			
		

> Ich habe die Klasse 'Auto'.
> Im Standardkonstruktor main()


Schon der erste grobe Fehler: Konstruktoren heißen immer so wie die Klasse selbst. Der Standard-Konstruktor zu Auto heißt also Auto(). Das, was du main() nennst, ist mit an Sicherheit grenzender Wahrscheinlichkeit der Einsprungpunkt für das Betriebssystem (bzw. der VM).

Ark


----------



## Mesqualito (15. Nov 2008)

Da sag ich mal: ja  - das fördert die Gemeinsamkeit...


Und zwar hab ich das so verstanden, dass jede Klasse die main() - Methode hat.

Fängt doch immer so an:

```
package Verstaendnis;

// hier ein eventueller 'import'

public class NeueKlasse
{
    public static void main(String[] args)
    {
     // Variablendefinitionen
     // Überschreiben/Überladen der Standardmethode main() der Klasse 'NeueKlasse' mit
    //  z.B. public NeueKlasse()
    //  {
    //      public static int erweiterung = 1;
    //   }
    // zusätzliche Methodendefinitionen
    }
}
```


Aufruf des Konstruktors mit:

```
NeueKlasse ErsteInstanz; // Definition des Typs der "Variablen" 'ErsteInstanz'
ErsteInstanz =  new NeueKlasse(); // Setzen des Verweises bezüglich des Objekts 'ErsteInstanz'
```

Analyse:
Name der aufgerufenen Methode in der Klasse 'NeueKlasse':
main()  // solange keine Überladung/Überschreibung definiert ist

Das dachte ich verstanden zu haben.
Bleiben noch die offenen Fragen meines ersten Threads?!?


----------



## Fu3L (15. Nov 2008)

"public static void main(String[] args)" ist der Einstieg der VM in ein Programm (wie Ark schon geschrieben ha), d.h. an dieser Stelle beginnt dein Programm und nur eine Klasse in einem Programm braucht diese Methode, damit das komplette Programm gestartet werden kann. Ein Konstruktor sorgt für die initialisierung eines Objektes, das sind also 2 komplett verschiedenen Dinge:


```
public class Auto {

  public Auto() {

    System.out.println("Hier wird eine Instanz von Auto erzeugt und zurückgegeben");

  }

  public hupen() {

    System.out.println("HUUPPP");

  }

  public static void main(String[] args) {

    Auto a = new Auto();
    a.hupen();

  }

}
```

Die VM beginnt in der Main Methode, sieht, dass ein Auto erzeugt werden soll und ruft den Konstruktor, Auto(), auf. Auto() gibt ein Auto zurück. Danach kann die VM für Auto die Methode hupen() aufrufen. Die Ausgabe wäre also:



> Hier wird eine Instanz von Auto erzeugt und zurückgegeben
> HUUPPP



Danach ist das Ende der Main-Methode erreicht und das Programm wird beendet.

Edit: Variablen schreibt man übrigends normalerweise klein, wenns keine Konstanten sind....


----------



## Fu3L (15. Nov 2008)

Da dir Überladung auch nicht klar zu seien scheint:

Bei der Überladung werden Methoden nciht überschrieben. Sie werden nur ein zweites mal definiert und zwar mit anderen Parametern.


```
public class Auto {

	Auto() {
	
		System.out.println("Hier wird eine Instanz von Auto erzeugt und zurückgegeben"); 
		
	}
	
	Auto(String name) {
	
		System.out.println("Hier wird eine Instanz von Auto erzeugt und zurückgegeben"); 
		System.out.println("Der Name des Autos lautet: " + name); 
		
	}
	
	schalten() {
	
		System.out.println("Ich schalte einen Gang höher")
		
	}
	
	schalten(int gang) {
	
		System.out.println("Ich schalte in Gang: " + gang);
		
	}
	
	public static void main(String[] args) {
	
		Auto a = new Auto("Audi");
		a.schalten();
		a.schalten(4);
		
	}
	
}
```

Dies führt zu folgender Ausgabe:




> Hier wird eine Instanz von Auto erzeugt und zurückgegeben
> Der Name des Autos lautet: Audi
> Ich schalte einen Gang höher
> Ich schalte in Gang: 4


----------



## P (15. Nov 2008)

Hi,

hab dir hier mal ein kleines Beispiel gebastelt, das vieles klarer werden lassen sollte.

Es gibt also eine Klasse "Auto", die eine statische Variable zum Speichern der Räder aller Fahrzeuge hat. Erstelle ich also ein Auto mit "new Auto();", wird durch die Methode "getRaeder" die Anzahl der Räder von einem Auto ermittelt: 4.
Wenn ich nun ein 4er-Auto (was auch immer das sein mag), erstelle mit "new Auto(4)" ein Objekt, das die Methode getRaeder(4) aufruft, die 16 zurückgibt und diese Zahl wird anzRaedern addiert.
An dieser Stelle hatten wir also eine "Überladung", d.h. zwei mal den "gleichen" Konstruktor, die sich aber in den Parametern unterscheiden. Sie müssen sich entweder in der Anzahl oder in der Anordnung unterscheiden:

Auto() und Auto(int i) sind zu unterscheidene Konstruktoren (Anzahl der Parameter), also gültig.
Auto(int i) und Auto(String s) sind ebenfalls gültig, da man sie anhand der Parametertypen unterscheiden kann.
Auto(int i, int j) und Auto(int k, int l) sind nicht gültig, da beide die gleiche Anzahl von Parametern haben UND sich nicht in ihren Typen unterscheiden.


Die zweite Klasse LKW erbt von der Klasse Auto, d.h. sie hat alle Eigenschaften der Elternklasse.
Jetzt kommt die große Überraschung 
Rufe ich nun "new LKW();" auf, wird der entsprechende Konstruktor aufgerufen, der aber anscheinend nichts macht. Tja, von wegen. Es wird einfach und ohne meinen Willen super(); aufgerufen, also den Konstruktor der Elternklasse (an dieser Stelle könnte ich aber auch super(5) aufrufen, um den anderen Konstruktor zu wählen).
Nun steht aber im Auto()-Konstruktor, dass er getRaeder() aufrufen soll und das ist ja falsch, da ja nur jeweils 4 Rädern vom Auto hinzuaddiert werden würden. Und genau dazu "überschreiben" wir die Methode getRaeder().
Die Methode muss den gleichen Namen und die gleiche Anzahl von Attributen bzw. auch die gleichen Typen in der gleichen Reihenfolge haben, quasi "genau so aussehen". In LKW() rufe ich zwar den Konstruktor der Elternklasse auf, der widerum getRaeder() aufruft, aber er weiß, dass ich ein LKW-Objekt erstelle und es wird geschaut, ob es nicht in der LKW-Klasse eine Methode mit diesem Namen gibt. Und Tatsache, es gibt sie. 

Hoffe, es ist klarer geworden  einfach mal versuchen, die Beispiele nachzuvollziehen.


```
public class Auto {

    protected static int anzRaeder = 0;
    
    protected Auto() {
        anzRaeder += getRaeder(1);
        
    }
    
    // Überladung des Konstruktors Auto. 
    protected Auto(int anzahl) {
        anzRaeder += getRaeder(anzahl);
    }
    
    protected int getRaeder(int anzahlAutos) {
        return anzahlAutos * 4;
    }
    

}
```



> public class LKW extends Auto {
> 
> private LKW() {
> 
> ...



PS: warum wird letzter Code nicht mit Highlights versehen?


----------



## Mesqualito (15. Nov 2008)

Danke für die Antworten, hat mir tatsächlich auf die Sprünge geholfen!

Hab da wohl erst einmal etwas durcheinander gebracht 

Ich werde den Code trotzdem gleich mal abpinseln und durchdenken.

Und gleich dazu lernen, wie man das Thema als abgehakt markiert...


----------

