Klassen Sinn des Konstruktors

  • Themenstarter Themenstarter alpha-nbg
  • Beginndatum Beginndatum
A

alpha-nbg

Gast
Hallo,

ich fange gerade an Java zu lernen und bin gerade an der Stelle wo es darum geht eine eigene Klasse zu schreiben. Wie ich das jetzt verstanden habe, wird der Konstruktor dazu benutzt um die Variablen mit den Übergabeparametern zu inizialisieren. Ich habe hier mal ein kleines Beispielscript aus einem Tutorial:

Java:
class HalloObjekt
{
  String mitteilung;

  HalloObjekt( String str )
  {
    mitteilung = str;
  }

  void sprich()
  {
    System.out.println( mitteilung );
  }
}

class HalloTester
{
  public static void main ( String[] args )
  {
    HalloObjekt einObjekt = new HalloObjekt("Eine Mitteilung!");
    einObjekt.sprich();
  }
}

Was mir jetzt nicht klar ist: Ich benutze doch die Methode einObjekt.sprich();
Warum übergebe ich nicht gleich der Methode den String also so:

Java:
void sprich(String text){.....}

Ich habe das getestet und das funktioniert genauso. Für was also einen Konstruktor bauen, wenn ich doch sowieso eine Methode aufrufe, der ich auch gleich die parameter übergeben kann. Irgendwie ist da der Groschen bei mir noch nicht gefallen.

Gruß,
Armin.
 
Und was ist, wenn du diese Mitteilung im Objekt brauchst? Außerdem ist der Konstruktor nicht dazu da "um einfach nur Parameter zuzuweisen". Du kannst da ja Objekte initialisieren usw. Aber zurück zu deinem Beispiel. Stell dir vor dieses Objekt dient als Container für die Übertragung. Also muss der Text IN das Objekt, damit er von da, wo es gebraucht wird, abgerufen werden kann.
 
Danke für die schnelle Antwort. Wahrscheinlich war das Beispiel in dem Tutorial nicht gut gewählt, weil hier der Sinn des Konstruktors nicht erkennbar ist. Es ist parktisch so, dass in einem Objekt auch Aktionen ausserhalb der Methoden ablaufen und ich deshalb auch Variablen ausserhalb der Methoden brauche. Wie du ja geschrieben hast kann ich da noch weitere Objekte initialisieren. Das heisst also auch, dass Werte die ich direkt an eine Methode übergebe nur in dieser existieren und gültig sind, aber Werte die ich an den Konstruktor übergebe, von allen Methoden benutzt werden können - also sozusagen innerhalb des Objektes global sind?
 
Nein, es sind nur Werte "im Objekt global", die dort als Felder definiert werden, so wie mitteilung. Wo die ihren Wert her haben ist egal.
Der kann auch in einer normalen Methode gesetzt worden sein.

Zu deinem Konstruktor-Problem: Stelle dir vor, jemand der nicht weiß, was das Objekt ausgeben würde ruft die Methode auf.
Der kann das dann schlecht als Parameter übergeben.
 
Der Konstruktor dient der Initialisierung, ist er erfolgreich abgearbeitet, sollte das Objekt "vernünftig benutzbar" sein (wenn man sich an die Konventionen hält). Dazu zählt z.B. auch, dass der Konstruktor finale Variablen setzen darf, die später nicht mehr geändert werden können, und das der Konstruktor bestimmen kann, welcher Konstruktor der Oberklasse aufgerufen wird. Beides sind Dinge, die normale Methoden u.s.w. nicht können.
 
Nein, nicht ganz. Den Gültigkeitsbereich bestimmst du selber:
Java:
class Beispiel {
  private String text;
  public Beispiel() {
    text = "Standardblabla";
  }
  public Beispiel(String s) {
    text = s;
  }
  public setText(String s) {
    text = s;
  }
  public print() {
    System.out.println(text);
  }
}

class Tester() {
  public static void main(String[] args) {
    Beispiel bsp1 = new Beispiel();
    bsp1.print();
    Beispiel bsp2 = new Beispiel();
    bsp2.setText("Durch eine Methode gesetzt");
    bsp2.print();
    Beispiel bsp3 = new Beispiel("Direkt im Konstruktor übergeben");
    bsp3.print();
  }
}

Von daher stimmt dein Punkt nicht so ganz. Deutlicher wird vermutlich folgendes (sofern dich die Liste nicht zu sehr verwirrt)
Java:
class Container {
  private List<String> eineListe;
  public Container(String[] parameter) {
    eineListe = new ArrayList<String>();
    for (int i=0;i<parameter.length;i++) {
      eineListe.add(parameter[i]);
    }
  }
}

Im Konstruktor machst du also das, was du bei dem Konstruieren des Objektes für notwendig hälst
 
Aha, ich kann den Konstruktor mehrmals in einer Klasse definieren:

Java:
  public Beispiel() {
    text = "Standardblabla";
  }
  public Beispiel(String s) {
    text = s;
  }

Ich habe das script mal im Debugger laufen lassen. Je nachdem ob ich beim erzeugen des Objektes einen String übergeben habe oder nicht, wird der entsprechende Konstruktor ausgeführt. Ich hatte das bisher so verstanden, dass es nur einen Konstruktor geben darf. Das ist interessant. Wieder was dazugelernt. Ich muss mich erst noch an den Objektorientierten Ansatz gewöhnen. Aber das wird schon langsam. Danke schonmal an alle für euere Hilfe.
 
Du kannst die Konstruktoren auch verschachteln:
Java:
public Beispiel() {
  this("Standardblabla");
}
public Beispiel(String s) {
  text = s;
}

Weiß zwar nicht womit du lernst, aber es sollte früher oder später da auch erwähnt werden.
 
ich habe mir ein paar Tutorials im WEB zusammengesucht. Vielleicht sollte ich mir auch noch ein Buch zulegen. Aber das mit dem Konstruktor ist mir jetzt schon einigermassen klar geworden.
 
Objektorientierung verwendest Du zum Ordnen und Strukturieren. Überleg Dir kurz, was Du überhaupt ordnen kannst. Im wesentlichen sind das Funktionen und Daten.
Ein Objekt (also die konkrete "Instanz" einer Klasse) ist eine Kapsel, die eine bestimmte Menge von Daten aufbewahren und mit dazugehörigen Funktionen verarbeiten kann. Sowohl die Daten, als auch die Funktionen sind Teil des Objekts und liegen "innerhalb".
Damit musst Du Dich "außerhalb" nicht mehr befassen bzw. Daten und Funktionen überhaupt nicht mehr sehen.

Wenn Du nun eine Objektklasse hast, die gar keine Daten speichert, also keinen inneren Zustand besitzt, dann wird da ein großer Vorteil der Objektorientierung nicht genutzt. (kann trotzdem sinnvoll sein)
In so einem Fall ist das Verhalten aller Funktionen dieser Klasse nur von den Parametern abhängig, mit denen einen Funktion aufgerufen wird.
Thema "statische Methoden" -> lesen 😉

Erweitere doch mal Dein Beispiel. Gib dem Objekt ein zusätzliches Attribut, indem Du der Klasse eine Variable hinzufügst. Beispielsweise eine Zählvariable.
Bei jedem Aufruf der Funktion "sprich" lässt Du den Text ausgeben und erhöhst die Variable um eins.
Dann fügst Du eine weitere Funktion (Methode) hinzu und nennst sie z.B. "nutzung". Mit dieser Funktion lässt Du den aktuellen Wert der Zählvariable ausgeben.
Das ist der Moment, wo das Verhalten der Funktion nicht nur von den Parametern (sie hat erstmal keine) sondern vom inneren Zustand des Objekts abhängig ist.
Jetzt hast Du beides in Deinem Objekt gekapselt. Die nötigen Daten, die das Objekt braucht und die Funktionen, die (einigermaßen) sinnvoll zu dem Objekt gehören.
Du kannst nun mehrere dieser Objekte erzeugen und jedem eine andere Nachricht geben. Jedes Objekt kann unterschiedlich oft die Methode "sprich" ausführen und gibt dann auch entsprechend unterschiedliche Zähler aus.

Es klingt, als hättest Du bisher "Nicht-Objektorientiert" programmiert. Stell Dir vor, wie das Beispiel dort aussehen würde, um die Unterschiede zu finden.
Objektorientierung macht bei so kleinen Beispielen einen ziemlichen Wasserkopf und die ganze Sachen nicht wirklich angenehmer.
Aber bei größerem Umfang der Anwendung lässt sich damit (meist) deutlich mehr Ordnung reinbringen.
Der Konstruktor soll(te) das Objekt in einen regulären Zustand bringen, in dem es dann verwendet werden kann.
Die Methoden des Objekts sorgen dafür, dass nur zulässige Veränderungen möglich sind. (falls man denn keine Fehler macht ^^)
Übertrage das mal auf beispielsweise C. Wenn Du beim erzeugen von Daten ohne Objektorientierung etwas vergisst, dann fehlt da etwas. Hast Du einen Konstruktor, der das kapselt, dann kannst Du zumindest mal sicher sein, dass die Objekte auch gleichartig erzeugt werden.
Der Konstruktor gibt Dir einen sauberen Start, ohne dass Du "von außen" darüber nachdenken musst.
 
Zuletzt bearbeitet:
Hallo,

Danke für die ausführliche Beschreibung. Ja stimmt ich habe bisher immer rein funktionsorientiert programmiert. An den objektorientierten Ansatz muss ich mich erst noch gewöhnen.
 
man könnte doch das Beispiel erweitern

man füge neue methoden hinzu:

Java:
public void sprichEnglish(){
		//übersetze
		//...
		//
		System.out.println(mitteilung);
	}
	
	public void sprichItalienisch(){
		//übersetze
		//...
		//
		System.out.println(mitteilung);
	}


:toll:
 

Neue Themen


Zurück
Oben