Java Objekte lernen?

...komplette Frage anzeigen

6 Antworten

Ach mach dir da keine Sorgen. Objektorientierung checkt am Anfang wirklich niemand ;).

Und selbst von denen, die der Meinung sind es kapiert zu haben, hat es ein guter Teil trotzdem nicht begriffen ;). Auch der Grund, wieso ich dir tunlichst von Youtube abraten würde - vorrausgesetzt du willst es wirklich richtig lernen. Was man da hört ist manchmal wirklich grußelig...

Was man natürlich als Anfänger nicht merken kann - denn die Spielfigur hüpft durch den Bildschirm und man freut sich.

Einführung

Ach ja: Bist gerade mein "Versuchsobjekt". Würde mich also über kurzes Feedback freuen, ob man den Text unten versteht ;). Und ob das hilfreich war ;).

Vielleicht mache ich ja irgendwann eigenes Java-Tutorial oder Blog oder so etwas. Das ist eher so als Test geschrieben, ob Erklärungen in dieser Art funktionieren. Nicht dass du dich wunderst ;).

Ist ein bisschen länger geworden...

Mal von mir ein kurzer Versuch der Erklärung:

Du wirst bisher eben in eine Haupt-Klasse bereits Funktionen definiert haben. Bisschen Grundrechenarten. Variablen erzeugen und Werte zuweisen. if, for und while. So etwas eben.

Das hat man früher auch gemacht.

Gut - nicht ganz am Anfang (da gabs Goto und das ist richtig böse). Jedenfalls hat man in dieser Art, wie du kennst, einfach so vor sich hinprogrammiert. Wenn eine Datei zu groß wurde, hat man eben in der nächsten Datei weitergemacht. Aber genau dieser Programmierstil.

Computer wurden immer schneller. Die Leute wollten, dass die Computer auch immer mehr konnten. Und man hat immer mehr Code geschrieben.

Und dann hat niemand mehr die Programme geblickt.

Stell dir vor, du hast da wirklich Millionen von Zeilen Code vor dir liegen - und nicht nur die paar Hundert, die du so hingeschrieben hast. Wie willst du da noch auch nach einem Monat wissen, wieso du eine gewisse Zeile irgendwann mal hingeschrieben hast und was die macht (Spoiler: Ja, das geht. Erfordert aber viel Disziplien und Zeit).

Wird auch häufig als "Softwarekrise" bezeichnet:

https://de.wikipedia.org/wiki/Softwarekrise

Eine Lösung musste her!

Und deshalb hat man sich Konzepte überlegt, wie man gigantisch Große Programme schreiben kann ohne den Überblick zu verlieren.

Eines dieser Konzepte ist Objektorientierung.

Und auch wenn du bis jetzt kein bisschen schlauer bist, was Objektorientierung eigentlich ist: Diesen Hintergrund zu kennen ist essentiell, dass man überhaupt versteht, wieso man das eigentlich macht, was man bei Objektorientierung macht.

Die Idee hinter Objektorientierung

Stell dir ein ganz großes Verwaltungsgebäude vor.

Ganz viele Schalter (=Objekte). Und jeder Schalter hat genau 2 Sachen:

* Einen Aktenschrank mit verschiedenen Daten

* Eine Person, die herumsitzt und der du Fragen stellen oder Anweisungen geben kannst

Das interessante ist aber, dass jeder Schalter eine genau definierte Aufgabe hat.

z.B. wird es einen Schalter geben um eine Überweisung aufzugeben. Dieser Schalter bietet also eine bestimmte Funktion "überweise(Quelle, Ziel, Betrag)" an.

Du möchtest 10 Euro an die Deutsche Bahn überweisen.

Du gehst zum Schalter und sagst: uberweise(MeinKonto, DB_Konto, 10). 

Und jetzt kommt der Witz an der Geschichte: Nachdem du das dem Schalter gesagt hast, gehst du weg. Und du musst nun überhaupt nichts mehr machen. Du musst dich nicht darum kümmern, dass die Überweisung aufgegeben wird. Das macht nun der Schalter.

Die Arbeit des Überweisungsschalters

Der Überweisungsschalter wird nun zu seinem Aktenschrank gehen und da hermwühlen. Und dein Konto suchen. Und es finden. Und prüfen, ob genügend Geld da ist. Und das Geld abziehen.

Jetzt stellt dein Überweisungsschalter fest: Mist! Das Zielkonto wird von einer anderen Bank überweisen.

Und was wäre jetzt das logische?

* Überweisungsschalter hackt sich auf den Server/Aktenschrank der anderen Bank und verändert dort das Zielkonto

* Überweisungsschalter gibt die Überweisung weiter an die Zielbank

Und gerade auf Youtube werden dir viele Leute Weg 1 programmieren. Mit dierser Schalteranalogie stellt man fest: Ist ziemlicher Blödsinn ;).

Da wir auch nicht so genau wissen, wo denn die Zielbank überhaupt ist (wieso denn auch) freuen wir uns, dass es einen "Vermittlungsschalter" gibt. Wir rennen also zum Vermittlungsschalter und sagen: "Überweisung von 10 Euro auf Konto DB_KONTO der Bank XY". 

Und danach?

Sache für uns erledigt. Wir gehen zurück zu unserem Schalter und Verlassen uns darauf, dass die Überweisung ankommt.

Der Vermittlungsschalter rennt in dieser Zeit zu seinem Aktenschrank. Sucht heraus, wo die Zielbank ist. Rennt zum Schalter der Zielbank. Und sagt: "Überweise 10 Euro auf DB_KONTO".

Dann ist der Vermittlungsschalter fertig und kann Mittagspause machen.

Der Zielbankschalter rennt zu seinem Aktenschrank. Sucht das DB_KONTO heraus und schreibt 10 Euro mehr drauf.

Du merkst: Der einzige, der auf den Aktenschrank (also auf die Daten) zugreifen kann und tut ist der jeweilige Schalter!

Und das ist eines der wichtigesten Prinzipien von Objektorientierung.

Was hat Objektorientierung noch zu bieten?

Klassen wirst noch gehört haben.

Was ist denn das schon wieder? Du stehst im Berliener Hauptbahnhof und möchtest ein Ticket kaufen. Da wird mehr als nur ein Ticketschalter stehen ;).

Wäre ja schon blöd, wenn wir jeden einzelnen Ticketschalter einzeln programmieren müssten - weil jeder Ticketschalter ist ja ein Objekt.

Deshalb kann man sagen, ein Ticketschalter ist so etwas und jeder Ticketschalter hat einen Aktenschrank der so aussieht und bietet diese Funktionen (eigentlich Methoden in Objektorientierung genannt) an.

Diese Beschreibung nennt sich "Klasse". Klassen sind Baupläne für Objekte. Klassen sorgen dafür, dass du nicht jedes Objekt einzeln programmieren musst. Sondern ein mal eine Beschreibung z.B. für Ticketschalter.

Und dann kannst du dir mit "new" beliebig viele konkete Ticketschalter wie: "Schalter 1", "Schalter Nord", "Schalter XY" bauen. Deren Programmierung durch die Klase bestimmt ist.

Später kann man dann sogar sagen: Es gibt eine Gruppe spezieller Ticketschalter wie z.B. für den Nahverkehr. Und die sind den normalen Ticketschalter sehr ähnlich. Aber das hat Zeit ;).

Übertragung auf Java

Aber genau so wie oben muss man das in Java abbilden. Muss man eben nur wissen, wie das in Java geht. Aber das ist reine Übung.

Noch nicht 100% lauffähig ;). Aber hab da mal schnell was auf pastebin geschrieben:

https://pastebin.com/47MHvyAc

Gruß

Tuxgamer

Mit der Objektorientierung versucht man die Programmierung zu vereinfachen, indem man Objekte aus der realen Welt auf die digitale überträgt. Dies kann alles sein: Autos, Lampen, Menschen, etc. Um ein solches Objekt zu erzeugen, benötigt man einen Bauplan. Wenn du in echt nämlich ein Gebäude oder eine Maschine baust, brauchst du auch einen. In der digitalen Welt nennt man diesen Bauplan Klasse. 

Die Klasse legt fest, welche Eigenschaften und Methoden später nach diesem Bauplan erzeugte Objekte haben sollen. Nehmen wir mal das Beispiel Fahrzeug:

class Fahrzeug {

}

Zunächst müssen wir uns überlegen, welche Eigenschaften ein Fahrzeug auszeichnen. Wodurch unterscheiden sich Fahrzeuge?

class Fahrzeug {
   public String farbe;
   public double geschwindigkeit;
   ...
}

Bisher kannst du Objekte nach diesem Bauplan erzeugen, die sich durch bestimmte Eigenschaften auszeichnen:

Fahrzeug fahrzeug = new Fahrzeug();
fahrzeug.farbe = "rot";

Du kannst dabei direkt auf die einzelnen Eigenschaften zugreifen und so z.B. die Farbe ändern. Gebräuchlicher und auch deutlich empfehlenswerter sind aber sogenannte Getter und Setter. Getter teilen dir den Wert einer Eigenschaft mit. Setter setzen den Wert einer Eigenschaft. Erstellen wir jetzt mal beispielhaft einen Getter und einen Setter für die Eigenschaft geschwindigkeit:

private double geschwindigkeit;
...
public String getGeschwindigkeit() {
   return geschwindigkeit;
}
public void setGeschwindigkeit (double geschwindigkeit) {
   if (geschwindigkeit > 0) {
      this.geschwindigkeit = geschwindigkeit;
   }
}

Du siehst, die Eigenschaft ist jetzt private, d.h. man kann auf sie nur innerhalb der Klasse selbst zugreifen. Um den Wert von außerhalb zu setzen, muss der Setter aufgerufen werden. Hier sieht man schon direkt einen der Vorteile, die Setter einem bieten: Man kann direkt überprüfen, ob der zuzuweisende Wert überhaupt sinnvoll ist. So kann verhindert werden, dass durch falsche Werte der Programmablauf gestört wird.

Nun muss unser Fahrzeug aber auch etwas tun können außer zu existieren. Wir implementieren also noch einigen Methoden:

...
public void beschleunigen() {
   double geschwindigkeit = getGeschwindigkeit();
   setGeschwindigkeit(geschwindigkeit + 1);
}
public void bremsen() {
   double geschwindigkeit = getGeschwindigkeit();
   setGeschwindigkeit(geschwindigkeit - 1);
}

Wir gehen hier davon aus, das wir alle Eigenschaften nun als private deklariert haben und Getter und Setter erstellt haben.

Wir können außerdem noch einen Konstruktor einfügen. Dies ist eine Methode, die aufgerufen wird, wenn ein Objekt der Klasse erzeugt wird. Dadurch können wir sicher stellen, dass alle relevanten Eigenschaften jederzeit gesetzt sind:

Fahrzeug(String farbe) {
   setFarbe(farbe);
   setGeschwindigkeit(0);
}


Dann gibt es noch Vererbung. Das bedeutet nichts weiter, als dass wir einen weiteren Bauplan erstellen, welcher aber aus einem anderen hervorgeht. Z.B. können wir nun einen Bauplan für ein Auto ergänzen, welcher von der Klasse Fahrzeug erbt. Damit erhält er alle Eigenschaften und Methoden, die die Klasse Fahrzeug besitzt. Zusätzlich werden autospezifische Eigenschaften und Methoden ergänzt:

class Auto extends Fahrzeug {
   private int leistung;
   private double hoechstgeschwindigkeit;
   private double beschleunigung;
   private double hubraum;
   private int anzahlGaenge;
   private int aktuellerGang;
   ...

   public void setGang(int gang) {
      if (gang > 0 && gang <= anzahlGaenge) {
         aktuellerGang = gang;
      }
   }
   ...
}


Wir können nun also wieder die Getter und Setter einfügen. Ebenso können wir einen eigenen Konstruktor erstellen, in dem nicht nur die Farbe gesetzt wird, sondern auch die Leistung, Höchstgeschwindigkeit, ...

Genauso können wir auch eine Klasse Fahrrad erstellen. Diese erbt von der Klasse Fahrzeug und verfügt zusätzlich über Eigenschaften wie dynamoart oder ventilartVorne und Methoden wie lichtAnschalten() oder reifenAufpumpen().

Ich weiß, das ist alles sehr weit weg von der digitalen Realität. Deshalb empfehle ich dir, wenn du dies einigermaßen verstanden hast, eine dynamische Liste selbst zu implementieren. Diese funktionieren nämlich so, dass es Knoten gibt, die jeweils auf den nächsten Knoten verweisen. Jeder Knoten ist ein Objekt, welches als Eigenschaften den Inhalt sowie die Referenz auf den nächsten Knoten besitzt. Einfach mal recherchieren und selbst ausprobieren. Dabei wird dir auch deutlich, dass Objekte nichts weiter als zusammengesetzte Datentypen sind.

Insgesamt benötigt man sehr viel Zeit (Monate), um dieses Thema zu durchschauen. Die Bücher vom Rheinwerk-Verlag sowie Online OOP-Tutorials fand ich früher sehr hilfreich. Aber gerade das Ausprobieren und die Erfahrung lassen einen das einfacher verstehen. Du hast Glück, dass du OOP mit Java erlernst. Ich habe dies nämlich mit PHP getan und habe den Sinn davon nicht verstanden, bis ich irgendwann Java gelernt habe. Java ist einfach die beste Sprache, um dieses komplexe Thema zu verstehen.

Tuxgamer2 05.07.2017, 15:53

Du kannst dabei direkt auf die einzelnen Eigenschaften zugreifen und so z.B. die Farbe ändern. Gebräuchlicher und auch deutlich empfehlenswerter sind aber sogenannte Getter und Setter. Getter teilen dir den Wert einer Eigenschaft mit. Setter setzen den Wert einer Eigenschaft. 

Ich verstehe es einfach nicht.

Wieso?

Wieso ist dieser Blödsinn immer noch so verbreite?

Du setzt deine Variablen private - was eine sehr gute Idee ist. Und im nächsten Moment machst du dir eine Hintertür auf, um auf die Variablen trotzdem zugreifen zu können.

Das ist keine Datenkapselung. Das ist lediglich Datenkapselung vortäuschen.

Geschwindigkeit ist eine Variable vom Fahrzeug. Und da hast du nicht drauf zuzugreifen - egal ob über public oder über getter/setter. Denn das ist mehr oder weniger nur syntaktischer Zucker.

Getter/Setter gerne, dann aber auch nur private.

Und von außen nur mit sinnvollen Methoden wie "beschleunigen" und "bremsen" zugreifen.

Fahrzeug(String farbe) {
setFarbe(farbe);
setGeschwindigkeit(0);
}

Am Rande: setGeschwindigkeit(0); ist eigentlich unnötig, weil Java sowieso class-member mit Typ double default als 0 initialisiert.

0
tavkomann 05.07.2017, 19:41

Du bist also der Meinung man sollte gar keine Getter und Setter verwenden. Und wie kommt man dann an die Eigenschaften heran? In Java selbst sind zahlreiche Getter und Setter implementiert. Ich verstehe jetzt nicht, was daran falsch sein soll. Und die Sichtbarkeit immer auf public zu setzen, macht doch sicherlich auch keinen Sinn. Ich gebe zu, Geschwindigkeit war jetzt nicht das beste Beispiel, weil hierfür ja die Methoden beschleunigen und bremsen existieren. Dann sind Getter und Setter natürlich nicht sinnvoll. Aber z.B. bei der Klasse Auto bietet es sich an die Leistung so zu realisieren. Natürlich macht es auch keinen Sinn, alle Eigenschaften von außen erreichbar zu machen. Man sollte dies nur mit jenen tun, bei denen es auch erforderlich ist. Kannst du deine Anmerkung bitte erläutern, damit ich verstehe, was du meinst?

0
Tuxgamer2 05.07.2017, 22:15
@tavkomann

Und wie kommt man dann an die Eigenschaften heran? 

Gar nicht ;).

Das ist doch gerade das "Geheimnissprinzip" oder "Datenkapselung" oder wie mans nennen will. Einzig das Objekt kennt seinen internen Zustand und kennst so seine Eigenschaften. Der Rest verwendet nur die vom Objekt bereitgestellten Methoden.

In Java selbst sind zahlreiche Getter und Setter implementiert.

Nicht alles, was in den Java-Bibliotheken gemacht wird, ist unbedingt gut.

Aber ist auch so, dass Bibliotheken programmieren noch mal etwas anderes ist als Applikationen. Bibliotheken hast du tatsächlich mehr die Situation: "Mach mal das und das und das". Und mit ganz vielen Optionen, da eine Bibliothek ja für ganz viele Fälle ausgelegt sein muss.

Meistens hast du dann gerne Wrapper-Klassen, die diese ganzen Getter und Setter aufrufen. Aber dann selber eher Methoden in Richtung "beschleunigen" haben - um dann für den Rest das ganze schöner Objektorientiert zu haben.

Und die Sichtbarkeit immer auf public zu setzen, macht doch sicherlich auch keinen Sinn. 

Nein - sicherlich nicht.

Und Sicherbarkeit auf public oder Getter + Setter ist das selbe. Mit ein bisschen syntaktischen Zucker ausenherum.

Kannst das ganz einfach nachprüfen: Ich könnte wahrscheinlich innerhalb eines Samstags ein Skript bauen, dass jede public Variable in einem Programm private macht und Getter und Setter verändert. Einfach ein bisschen Zeug replacen.

Von daher wird ziemlich schnell klar, dass ob ich public schreibe oder Getter und einen Setter - das nur anderer Syntax ist ohne Einfluss auf die restliche Struktur des Programmes.

Und da public Variablen strukturell ziemlich schlechter Stil sind, sind das Getter und Setter genauso.

Ich sage nicht, dass man keine Getter und Setter nutzen darf. An gewissen Stellen wird man das nicht vermeiden können. Aber wenn ich das mache, mache ich das überlegt und versuche es trotzdem so gut wie möglich zu vermeiden.

Ach ja: Und klar. In Java ist Getter und Setter anstatt public Variable tatsächlich syntaktisch sinnvoller und damit vorzuziehen. In anderen Sprachen ist das anders. z.B. C# oder python gibt es versteckte getter und setter, die du nachträglich zu jeder Variable hinzufügen kannst. 

Aber was mich gestört hat ist diese Einstellung: Public Variable böse aber mit Getter und Setter alles gut. Nein. Getter und Setter machen es nicht wirklich besser.

0
tavkomann 05.07.2017, 22:18
@Tuxgamer2

Wie würdest du dann in meinem Beispiel mit dem Auto verschiedene Objekte mit z.B. unterschiedlichen Leistungen realisieren? Nur über den Konstruktor?

0
tavkomann 05.07.2017, 22:24
@Tuxgamer2

Naja gut, ich kann dich in etwa verstehen. Ich habe gerade ein paar meiner bisherigen Java-Projekte angesehen. Tatsächlich waren da vielleicht nur 1-2 Getter/Setter. Aber ich denke, das hängt eher vom Einsatzzweck ab. Gerade bei solchen Sachen mit Swing gibt es viele Setter-Methoden.

0
Tuxgamer2 07.07.2017, 11:57
@tavkomann

Objekte mit z.B. unterschiedlichen Leistungen realisieren? Nur über den Konstruktor?

Yep. Leistung ist etwas, was das Auto ja einfach hat - und sich nicht so einfach verändert. Leistung eines Autos sieht man daran, eben wie schnell es beschleutigen kann etc. Von außen ist es also ziemlich irrelevant, was die Leistung des Autos ist.

Gerade bei solchen Sachen mit Swing gibt es viele Setter-Methoden.

Durchaus.

Da braucht man leider trotzdem sehr starke Bindung. Weshalb man dann meistens eine Klasse z.B. MeinFenster erstellt - die dann massig Getter/Setter zu JFrame aufruft - aber selber nach außen eine deutlich schönere Schnittstelle aufweißt.

Dass dann die unschönen Seiten von Swing nach außen hin gewrappt sind.

0
tavkomann 20.07.2017, 03:42
@Tuxgamer2

Gerade habe ich für eine Android-App eine bestimmte Library eingebunden. Dann ist mir diese Frage wieder eingefallen.

Denn der Konstruktor wird automatisch aufgerufen und nicht in der onCreate-Methode, sodass ich alles, was ich der Libraray mitgeben möchte über deren Setter-Methoden tun muss. Deswegen stehen bei mir gerade um die 10 Setter untereinander.

Sie sind also selten, doch es gibt durchaus sinnvolle Anwendungsgebiete ;)

0

Nein! Du bist nicht zu blöd, es ist ein schweres Thema für jemand der das noch nicht kennt. Für mich war es sehr schwer von Visual Basic auf OOP Sprachen umzusteigen. Das Verständnis dafür kommt mit der Übung.

Vielleicht stellst du dir Objekte als eine kleine Maschine vor die du in eine Variabe stecken kannst und wie ein Programm im Programm zur Ausführung bringst.

Den Bauplan für das Objekt stellt die Klasse dar.

Die wirklich komplizierten Sachen wie Vererbung und Polymorphismus kommen sowieso von selber dazu.

Die Objekt-Orientierung ist der Versuch, die Welt um ein Problem herum digital abzubilden. Alles sind Objekte. Ein Pflanze, ein Auto, ein Gedanke, ein Lied ... einfach alles lässt sich in Objekt beschreiben. 

- Objekte haben Funktionen (zB. kann ein Auto fahren)
- Objekte haben Eigenschaften (zB. hat ein Auto eine Anzahl von Türen)
- Objekte können sinnbildlich anderen Objekten untergeordnet werden
   (zB. ist ein Auto von KFZ abgeleitet)

In der Objekt Orientierung geht es um Datenkapselung und Zugriffsrechte. 

https://de.wikipedia.org/wiki/Objektorientierung
https://www.youtube.com/results?search_query=objekt+orientierung+tutorial+deutsch

YouTube ist immer ein gutes Hilfsmittel. Gerade bei OO hilft es sich die ganzen Sachen zu visualisieren.

Viel Spaß beim programmieren lernen!

Was möchtest Du wissen?