Die Denkweise der OOP oder: Hopfen und Malz verloren?

Sonnenblume

Mitglied
Hallo liebes Forum!

Ich habe mich eben hier angemeldet, nachdem ich in den letzten Tagen schon häufiger von Google hierher verwiesen wurde und auf einige konkrete Java-Fragen auch Antworten gefunden habe.

Seit einigen Wochen arbeite ich mich in Java ein. Ich bin Umsteiger von anderen Sprachen (hauptsächlich Fortran) und habe in den letzten fünf Jahren viel programmiert, auch etwas größere Projekte. Allerdings habe ich das programmieren größtenteils selbst mit Hilfe von Büchern und dem Verstehen anderer Leute Quellcode erlernt und kann schwer einschätzen, wie gut meine Programme wirklich waren. Es gab da niemanden, der mir gesagt hätte "hier kannst du was besser machen".

Jetzt muss ich Java programmieren (lernen) und mache eigentlich seit vier Wochen nichts anderes: Lese diverse Tutorials, Bücher, schaue Quelltext an, schreibe kleine Programme. Dabei war das Konzept der OOP für mich vollkommen neu. Ich habe also damit begonnen, Einführungen über Klassen, Objekte, Methoden usw. zu lesen und denke, dass ich das (in der Theorie) mittlerweile ganz gut verstanden habe. Aber es hapert an der Anwendung. Ich habe mittlerweile schon ein paar kleinere Programme geschrieben und es auch immer irgendwie so hinbekommen, dass das Programm nachher das machte was es machen sollte. Aber ich merke, dass ich diese objektorientierte Denkweise einfach noch nicht verinnerlicht habe. Ich kann mein Problem irgendwie in Klassen und Methoden aufteilen, ich kann den entsprechenden Quellcode schreiben und irgendwann läuft das Programm. Dabei ist aber noch ganz viel ausprobieren und weniger "ich weiß was ich hier tue". Speziell tue ich mich schwer damit, Instanzvariablen von Klassenvariablen zu unterscheiden (in der Theorie kein Problem!), zu entscheiden, wann ich etwas public oder private deklariere oder der Idee zu folgen, mit möglichst wenig Übergabeparamtetern zu arbeiten. Dass ich nicht direkt auf irgendetwas zugreife, sondern über Methoden oder Getter und Setter arbeite, damit ich die Variablen nicht öffentlich sichtbar machen muss. Es fällt mir schwer, meinen Quellcode von letzter Woche noch nachzuvollziehen.
Von der prozeduralen Programmierung bin ich es gewöhnt, dass man zunächst die ganzen Bausteine für *irgendwas* initialisiert, berechnet, whatever und dann alles zu etwas großem zusammensetzt. Jetzt ist es irgendwie umgekehrt: Ich erzeuge mir erst mal ein Objekt und dann schaue ich, was ich mit dem Objekt so alles anstellen kann.

Ich bin etwas frustriert, weil ich dachte, das müsste ich alles schneller lernen können. Ich habe gewisse Bedenken, dass ich das einfach nicht hinbekomme. Vielleicht bin ich nicht geschaffen dafür, objektorientiert zu programmieren und meinem Gehirn fehlen da ein paar nötige Windungen? Oder braucht es wirklich einfach Zeit und vier Wochen sind ein zu kurzer Zeitraum, um überhaupt schon etwas sagen zu können?

Ich danke euch fürs lesen!

Liebe Grüße,
Sonnenbljme
 
T

TryToHelp

Gast
Hallo Sonnenblume,

also ich würde sagen 4 Wochen sind dafür noch eine viel zu kurze Zeit um das komplex OOP zu lernen, zu verstehen und vorallem zu verwenden ;-) gib nicht auf, übe und dann wird es schon werden
 

Jango

Gesperrter Benutzer
OOP macht nur Sinn, wenn das Projekt größer ist und mehrere daran arbeiten.
Keiner schreibt dir vor oo zu programmieren, wenn es um einfache, schnelle Programme geht.
Einfach ne Klasse drumrumbauen und alles in die main schreiben. Das kommt der prozeduralen Programmierung nahe.
Nachhaltiger ist die ooP, aber nicht immer effektiver. ;)
 

Sonnenblume

Mitglied
Letztendlich soll es aber genau darum gehen: Ein großes Projekt zu entwerfen und umzusetzen. Was das sein wird, ist schon klar. Was fehlt, sind meine OOP-Fähigkeiten. Prozedural zu programmieren, ist keine Option (Anweisung von "oben") und ich denke bei dem, was nachher draus entstehen soll, ist der OOP-Ansatz auch gerechtfertigt.

Ich muss es also lernen, oder mir einen neuen Job suchen. Ich tendiere ganz stark zu ersterem, zumal ich wirklich Spaß an der Sache habe. Ich hab halt nur Angst, dass das mit dem lernen nicht klappt. :-(
 

FetterOtter

Bekanntes Mitglied
Gib dir Zeit. Ich musste vor 4 Jahren auf Java umsteigen, nachdem ich vorher fast 20 Jahre in PL1 programmiert hatte. Die alten eingeschliffenen Denkweisen schüttelt man so schnell nicht ab. Aber es wird...
 

jgh

Top Contributor
dann fange doch mal an...irgendein "kleines" prog von dir in oo zu ändern. kA auf welchem Level du gerade proggst, aber wenn deine Programme bspw. nur in der main-Methode stehen, wäre imho der erste Schritt sich entsprechende Methoden zu basteln..,
 

Sonnenblume

Mitglied
Meine main-Methoden sind eigentlich schon sehr bereinigt. Ich glaube, ich hab auch weniger Probleme damit, die Klassen und Objekte zu entwerfen (das geht ganz gut auf dem Papier), sondern an der konkreten Umsetzung. Mir leuchtet noch nicht ein, wann ich eine Variable im Klassenkopf deklarieren muss, wann ich this verwende (jemand sagte, this verwendet man bei Instanzvariablen, aber warum?). Dann habe ich probiert, etwas zu delegieren. Das hat geklappt, nachdem ich 1 zu 1 ein Beispiel aus einem Buch für meine Zwecke angepasst habe. Ich konnte auch nachvollziehen, was das Programm dann macht, aber so richtig einleuchtend, warum ich jetzt welches Objekt in welcher Klasse erzeuge, ist es nicht. Sorry für meine wirren Sätze, ich finde das gerade so schwierig zu formulieren.

Ich habe auch einfach den Eindruck, dass man mir nicht wirklich Zeit gibt. Es kommt alles auf einmal mit dem Kommentar "damit du es schon mal gesehen hast". Ich fühl mich etwas überfordert.
 
T

TryToHelp

Gast
Wie ich schon geschrieben hatte, ich glaube der Wandel zu OOP geht nicht so schnell, das dauert seine Zeit und das einzige was hilft ist üben, üben und üben ;-)
 

timbeau

Gesperrter Benutzer
Hi,

wenn dir auf dem Papier klar ist, welche Klassen und damit ja auch letztendlich Objekte du brauchst, sind dort die Variablen der Klasse ja schon definiert im Idealfall. Denke du postest mal ein Beispiel und konkretisierst. Ich benutze nur im Konstruktor this und in Settern. Ich würde da nicht viel Gedanken in diese Richtung verschwenden.
 

Sonnenblume

Mitglied
Hi,

wenn dir auf dem Papier klar ist, welche Klassen und damit ja auch letztendlich Objekte du brauchst, sind dort die Variablen der Klasse ja schon definiert im Idealfall. Denke du postest mal ein Beispiel und konkretisierst. Ich benutze nur im Konstruktor this und in Settern. Ich würde da nicht viel Gedanken in diese Richtung verschwenden.

So strukturiert sind meine Papier-Skizzen leider meistens nicht...

Gerade habe ich kein vernünftiges Beispiel zur Hand, aber wenn ich eins finde, werde ich es hier posten.
 

Landei

Top Contributor
Eigentlich ist OO nur eine "Neustrukturierung" deines Codes. Angenommen, du hast hast eine Funktion, die den Abstand zweier Punkte ermittelt, also
Java:
public double dist(double x1, double y1, double x2, double y2) {
   return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

Dann ist der erste Gedanke: "Ja, aber das x1 und y1 gehören doch zusammen!", und genau das gibt es dann auch als Records oder Structs in vielen Sprachen. Also

Java:
public class Point {
   public double x;
   public double y;
}

public double dist(Point p1, Point p2) {
   return Math.sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

Das Problem ist aber, dass das "Wissen", wie Punkte sich verhalten, immer noch außerhalb der Punkte vorhanden ist. Dabei ist es doch das, was Punkte eigenlich ausmacht und sie z.B. von einem Rechteck (was auch von zwei double-Werten beschrieben wird) unterscheidet. Und genau das ist die entscheidende Idee: Die Daten und das "Wissen" darum einfach zusammenzupacken:

Java:
public class Point {
   public double x;
   public double y;
   public double dist(Point that) {
      return Math.sqrt((this.x-that.x)*(this.x-that.x)+(this.y-that.y)*(this.y-that.y));
   }
}

Das ist genau die gleiche Formel wie vorher, nur diesmal an der Stelle, wo sie "logisch gesehen" hingehört: Bei genau den Dingsen, auf denen sie auch operiert. Damit wird alles "aufgeräumter", besser strukturiert und wiederverwendbarer. Alles andere (Kapselung, Vererbung, Überladen...) ist aus Erfahrungswerten resultierendes Beiwerk zu diesem Konzept.
 

Sonnenblume

Mitglied
Danke Landei, für den Quellcode. Ein bisschen hänge ich noch:
Beim untersten Beispiel übergibst du der Methode dist ein Objekt vom Typ Punkt, richtig? Aber worauf bezieht sich jetzt in der Methode this.x und that.x? this.x ist die Instanzvariable, die oben in der Klasse Punkt deklariert wurde. that übergebe ich beim Aufruf der Methode. Und jetzt bin ich durcheinander... Woher bekommt this.x Werte? Was ist der übergebene Punkt that? Ein in einer anderen Methode, z.B. der main-Methode in einer anderen Klasse, erzeugte Punkt? Im zweiten Beispiel übergibst du zwei Punkte, die irgendwelche Werte haben. Da ist mir das klar.

Und auch danke pappawinni. Die Struktur mit dem Bauplan und den Objekten kenne ich. Statische Variablen oder Instanzvariablen sind solche, die für jedes Objekt es Bauplans, also der Klasse, einen eigenen Wert haben. Z.B. hat jeder Punkt seine eigenen Koordinaten. Statische Variablen oder Klassenvariablen sind solche, die für die gesamte Klasse gelten, z.B. bei einer Klasse "Auto" die boolesche Variable "hatRaeder". Soweit richtig?
Aber wie passen jetzt Klassenmethoden dazu? Im Prinzip müsste es das gleiche sein: Eine Methode, die generell auf der ganzen Klasse wirkt, ist eine statische Methode. Nur vorstellen kann ich mir darunter nichts und mir fällt auch kein anschauliches Beispiel ein.
 
T

TryToHelp

Gast
das this heißt, es soll das x von diesem Objekt sein.
das that ist ein anderes Objekt das übergeben wird.
somit vergleiche ich von meinem Objekt (this.) den x wert mit dem objekt das mir übergeben wurde (that.) x theoretisch könnte man das this. dort weglassen ;-)
 
P

pappawinni

Gast
Naja, Sonnenblume, die Instanz des Punktes muss natürlich auch irgendwann mal erzeugt werden.
Dafür gibt es in der Regel einen Konstruktor in der Klasse, anderfalls wird der default-Konstruktor verwendet.
Damit erhalten die Instanzvariablen dann ihre Werte.
Es hätte wahrscheinlich normalerweise in einer Klasse Point auch eine Setter und eine Gettermethode ...
Ist halt nur ein Beispiel.

[EDIT]
BTW: Du schreibst, dass du bislang in Fortran programmiert hast. Das finde ich erstaunlich. War das dann wenigstens Visual Fortran oder womöglich noch Fortran 77 ?
Geht es da um technische Berechnungen, oder wo verwendet man sowas noch?
[/EDIT]
 
Zuletzt bearbeitet von einem Moderator:

Noctarius

Top Contributor
Um Landeis 3. Beispiel zuende zu führen:

Java:
public class Main {

  public static void main(String[] args) {
    Point p1 = new Point(10, 15); // x = 10, y = 15
    Point p2 = new Point(20, 14); // x= 20, y = 14

    double dist1 = p1.dist(p2); // p1 == this, p2 == that
    double dist2 = p2.dist(p1); // p2 == this, p1 == that
  }

}
public class Point {
  private double x; // internal var x
  private double y; // internal var y

  public Point(double x, double y) {
    this.x = x; // sets the internal var x of this instance to x
    this.y = y; // sets the internal var y of this instance to y
  }

  public double getX() {
    return x; // returns the value of the internal var x
  }

  public double getY() {
    return y; // returns the value of the internal var y
  }

  public double dist(Point that) {
    return Math.sqrt((this.x-that.x)*(this.x-that.x)+(this.y-that.y)*(this.y-that.y));
  }
}

[c]this[/c] ist also eine Referenz auf die aktuelle Instanz in dessen Scope die Methode ausgeführt wird.
 
Zuletzt bearbeitet:
P

pappawinni

Gast
Eine Methode, die generell auf der ganzen Klasse wirkt, ist eine statische Methode. Nur vorstellen kann ich mir darunter nichts und mir fällt auch kein anschauliches Beispiel ein.

Naja, Sonnenblume. Mal ein einfaches Beispiel.
Du hast eine Klasse Student und möchtest die Anzahl der Studenten (bzw. die Anzahl der Instanzen) erfassen.
Das kannst du dann mit einer Klassenvariablen realiseren.
Im Konstruktor der Klasse inkrementierst du dann halt die Klassenvariable, so dass sie bei der Instanzierung hochgezählt wird.
Für die Abfrage dieser Klassenvariable nimmst du dann auch eine statische Methode.
 

Sonnenblume

Mitglied
Ok, ist mir klar. Sowohl der Punkt als auch die Klassenmethode.

Und zum Thema Fortran: Im Bereich der Numerik ist Fortran noch ziemlich verbreitet. Es gibt immer mal wieder Bestrebungen, das durch andere Sprachen abzulösen, hat sich bisher aber nicht durchgesetzt. Ich habe übrigens Fortran 90 gemacht.
 

Bernd Hohmann

Top Contributor
Und zum Thema Fortran: Im Bereich der Numerik ist Fortran noch ziemlich verbreitet. Es gibt immer mal wieder Bestrebungen, das durch andere Sprachen abzulösen, hat sich bisher aber nicht durchgesetzt.

Das wird auch kaum passieren, denn dazu müsste man erstmal die ganzen Libs portieren welche in ihrer Konstruktion über Jahre auf die jeweilige Sprache abgestimmt worden sind.

Wie sowas aussieht erfährt man wenn sowas wie ein JPEG oder MPEG encoder/decoder aus dem C-Referenzcode nach Java portiert wird - dagegen ist ein Friedhof nach einer Zombienacht noch richtig aufgeräumt.

Zu Deinen Umsteigerproblemen: die hatte ich auch.

Der Befehl von "oben", "nicht-Prozedural" zu Programmieren ist Käse - denn im Kern wird man Java immer recht prozedural herunterprogrammieren und darüberhinaus wirds auch schnell monolithischer als es einem lieb ist ("goto" lässt sich ja noch brauchbar eleminieren, "gosub" fehlt mir nach 16 Jahren immer noch).

Die Schwierigkeit beim Umdenken steckt nicht darin dass man OOP kapieren muss (das ist in Java noch trivial im Gegensatz von zB. LISP) sondern wann man besser von einer OOP-Konstruktion die Finger lässt (das ist häufiger der Fall als es einem lieb ist).

Bernd
 

Ähnliche Java Themen

Neue Themen


Oben