1. Objekte und Klassen

Heute erfahren Sie ein wenig darüber, wie ein typisches Java-Programm funktioniert. Hier ist die große Neuigkeit: Jedes Java-Programm besteht aus Klassen und Objekten.

Sie wissen bereits, was Klassen sind, aber was sind Objekte?

Ich beginne mit einer Analogie. Stellen Sie sich vor, Sie möchten ein kleines Schiff bauen. Zuerst müssen Sie einen Bauplan erstellen und diesen dann der Fabrik übergeben, wo ein Schiff entsprechend dem Bauplan gebaut wird. Oder vielleicht ein Dutzend. Oder so viele Schiffe, wie Sie möchten. Dutzende identischer Schiffe werden nach einem einzigen Bauplan gebaut. Das ist hier das Wichtigste.

Das Gleiche gilt für die Java-Programmierung.

Blaupausen

Ein Programmierer ist wie ein Designer. Ein Designer erstellt Blaupausen und ein Java-Programmierer schreibt Klassen. Teile werden auf Basis der Blaupausen erstellt und Objekte werden auf Basis von Klassen erstellt.

Zuerst schreiben wir Klassen (erstellen Blaupausen), und während das Programm ausgeführt wird, erstellt die Java-Maschine Objekte basierend auf diesen Klassen. Genauso wie Schiffe aus Bauplänen entstehen.

Es gibt nur eine Blaupause, aber es können viele Schiffe sein. Die Schiffe sind unterschiedlich – sie haben unterschiedliche Namen und befördern unterschiedliche Ladungen. Aber sie sind sich sehr ähnlich: Sie haben alle das gleiche Design und können ähnliche Aufgaben erfüllen.

Oder hier ist eine andere Analogie ...

Ameisenhaufen

Ein Ameisenhaufen ist ein gutes Beispiel dafür, wie Objekte interagieren. In einem einfachen Ameisenhaufen gibt es drei Klassen von Ameisen: die Königin, Soldaten und Arbeiter.

Die Anzahl der Ameisen jeder Klasse ist unterschiedlich. Es gibt eine einzige Königin für den gesamten Ameisenhaufen, aber es gibt Dutzende Soldaten und Hunderte Arbeiterameisen. Drei Klassen und Hunderte von Objekten. Ameisen interagieren untereinander – mit Ameisen derselben Klasse und mit Ameisen anderer Klassen – nach strengen Regeln.

Das ist das perfekte Beispiel. In einem typischen Programm ist alles genau so. Es gibt ein Primärobjekt, das Objekte aller anderen Klassen erstellt. Die Objekte beginnen miteinander und mit der „Außenwelt“ des Programms zu interagieren. Das Verhalten der Objekte ist intern fest codiert.

Diese beiden Analogien sind zwei Seiten derselben Medaille. Die Wahrheit liegt in der Mitte. Das erste Beispiel (über einen Bauplan und Schiffe) zeigt die Beziehung zwischen einer Klasse und Objekten dieser Klasse. Das ist eine starke Analogie. Das zweite Beispiel (über einen Ameisenhaufen) zeigt die Beziehung zwischen den geschriebenen Klassen und den Objekten, die während der Programmausführung vorhanden sind.

Sie müssen zunächst Klassen für jedes Objekt schreiben, das im Programm vorhanden sein soll, und dann auch beschreiben, wie sie interagieren. Ja, das stimmt, aber es ist einfacher als es klingt.

In Java sind alle Entitäten zur Laufzeit Objekte, und beim Schreiben eines Programms geht es darum, die verschiedenen Arten der Interaktion von Objekten zu beschreiben. Objekte rufen einfach gegenseitig ihre Methoden auf und übergeben ihnen die erforderlichen Daten.

Dokumentation

Und woher wissen Sie, welche Daten an Methoden übergeben werden sollen? Die Menschen vor Ihnen haben an alles gedacht.

Jede Klasse verfügt normalerweise über eine Beschreibung, aus der hervorgeht, wofür sie erstellt wurde. Außerdem verfügt jede öffentliche Methode normalerweise über eine Beschreibung, die angibt, was sie tut und welche Daten an sie übergeben werden müssen.

Um eine Klasse verwenden zu können, müssen Sie eine allgemeine Vorstellung davon haben, was sie tut. Und Sie müssen genau wissen, was jede Methode bewirkt. Aber Sie müssen überhaupt nicht wissen, wie es das macht. Es ist wie ein Zauberstab.

Schauen wir uns den Code zum Kopieren einer Datei an:

Kopieren der Datei c:\\data.txt in die Datei c:\\result.txt
package com.codegym.lesson2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileCopy
{
   public static void main(String[] args) throws IOException
   {
      FileInputStream fileInputStream = new FileInputStream("c:\\data.txt");
      FileOutputStream fileOutputStream = new FileOutputStream("c:\\result.txt");

      while (fileInputStream.available() > 0)
      {
         int data = fileInputStream.read();
         fileOutputStream.write(data);
      }

      fileInputStream.close();
      fileOutputStream.close();
   }
}

Wenn Sie diesen Code Zeile für Zeile lesen, können Sie erraten, was er im Allgemeinen bewirkt. Allerdings erfordert das Erfahrung und Übung. Nach einer Weile wird Ihnen dieser Code bekannt und verständlich vorkommen.


2. Entwerfen eines Programms

Programmdesign ist eine ganze Kunst. Es ist gleichzeitig einfach und schwierig. Ganz einfach, denn es gibt keine strengen Gesetze: Erlaubt ist alles, was nicht verboten ist. Nun ja, und das macht es auch schwierig: Es gibt viele Möglichkeiten, etwas zu tun, und es ist nicht einfach, die beste zu finden.

Ein Programm zu entwerfen ist wie ein Buch zu schreiben. Einerseits schreibt man einfach Buchstaben, Wörter und Sätze. Andererseits sind Handlung, Charaktere, innere Widersprüche, Konflikte, Erzählstil, Intrigen usw. wichtig.

Die Hauptsache ist, zu verstehen, für wen Sie den Code schreiben. Und Sie schreiben Code für andere Programmierer .

Produktentwicklung bedeutet zwangsläufig Veränderungen: Hier wird etwas hinzugefügt, dort etwas anderes entfernt, etwas wird neu gestaltet. So entstehen aus kleinen Iterationen große, riesige und gigantische Projekte.

Das Wichtigste beim Code ist, dass er für andere Programmierer verständlich sein muss. Falscher Code, der verständlich ist, kann korrigiert werden. Korrekter, aber unverständlicher Code kann nicht verbessert werden.  Sie können es nur wegwerfen.

Wie schreibt man also guten, sauberen Code?

Dazu sind drei Dinge erforderlich:

  • Guten und verständlichen Code innerhalb von Methoden schreiben – das ist die einfachste Anforderung
  • Entscheiden, welche Einheiten in das Programm aufgenommen werden sollen
  • Das Programm korrekt in logische Teile aufteilen

Was steckt hinter diesen Konzepten?

Guten Code innerhalb von Methoden schreiben

Wenn Sie auch nur über grundlegende Englischkenntnisse verfügen, ist Ihnen vielleicht aufgefallen, wie einfach es manchmal sein kann, Code als englische Sätze zu lesen:

  • class Cat extends Pet– Das bedeutet, dass die Cat-Klasse die Pet-Klasse erweitert
  • while(stream.ready())— solange der Stream bereit ist...
  • if (a<b) return a; else return b– wenn akleiner als b, dann return a, andernfalls return b.

Das ist Absicht. Java ist eine von mehreren Sprachen, die es einfach machen, selbstdokumentierenden Code zu schreiben, also Code, der ohne Kommentare verständlich ist. In gutem Java-Code lesen sich viele Methoden genauso wie englische Sätze.

Beim Schreiben von Code besteht Ihre Aufgabe darin, ihn so einfach und prägnant wie möglich zu gestalten. Denken Sie einfach darüber nach, ob Ihr Code gut lesbar ist, und schon bewegen Sie sich in die richtige Richtung.

In Java ist es üblich, Code zu schreiben, der leicht lesbar ist. Vorzugsweise passt der gesamte Code für eine Methode auf einen einzigen Bildschirm (dh 20–30 Zeilen). Dies ist die Norm für die gesamte Java-Community. Wenn Code verbessert werden kann, sollte er verbessert werden.

Der beste Weg, zu lernen, wie man guten Code schreibt, ist durch Übung. Schreiben Sie viel Code, studieren Sie den Code anderer und bitten Sie erfahrenere Kollegen, Ihren Code zu überprüfen.

Und denken Sie daran, dass Ihr Wachstum in dem Moment stoppt, in dem Sie sich sagen: „Lassen Sie es gut genug in Ruhe.“

Entscheiden, welche Einheiten in das Programm aufgenommen werden sollen

Sie müssen Code schreiben, den andere Programmierer verstehen können. Wenn 9 von 10 Programmierern die Klassen A, B und C in den Entwurf eines Programms einbeziehen würden, sollten Sie auch die Klassen A, B und C in Ihr Programm aufnehmen. Sie müssen Code schreiben, den andere verstehen können.

Großartig, funktioniert, schnell, aber nicht standardmäßiger Code ist schlechter Code.

Sie müssen die Projekte anderer Leute studieren: Dies ist der beste, schnellste und einfachste Weg, die gesamte Weisheit aufzusaugen, die sich in der IT-Branche über Jahrzehnte angesammelt hat.

Und übrigens haben Sie bereits Zugriff auf ein hervorragendes, beliebtes und gut dokumentiertes Projekt – das Java SDK . Fangen Sie damit an.

Analysieren Sie die Klassen und wie sie organisiert sind. Überlegen Sie, warum einige Methoden statisch sind und andere nicht. Warum haben die Methoden die spezifischen Parameter, die sie haben, andere jedoch nicht. Warum genau diese Methoden, und warum heißen die Klassen so, wie sie heißen, und warum sind sie in ihren spezifischen Paketen enthalten.

Sobald Sie die Antworten auf all diese Fragen verstehen, können Sie Code schreiben, den andere verstehen können.

Dennoch möchte ich Sie davor warnen, den Code in den Methoden des Java SDK zu analysieren. Viele der Methoden wurden umgeschrieben, um die Geschwindigkeit zu maximieren, und ihre Lesbarkeit ist fraglich.

Das Programm korrekt in logische Teile aufteilen

Fast jedes Programm ist in Teile oder Module unterteilt. Jeder Teil ist für seinen eigenen Aspekt des Programms verantwortlich.

Ein Computer besteht aus einem Motherboard, einem Monitor und einer Tastatur – das sind alles separate, lose verbundene Teile. Darüber hinaus interagieren sie auf standardisierte Weise: USB, HDMI usw. Wenn Sie Kaffee auf Ihrer Tastatur verschütten, können Sie ihn einfach im Waschbecken abwaschen, trocknen lassen und dann weiter verwenden.

Aber ein Laptop ist ein Beispiel für eine monolithische Architektur: Es scheint, dass wir separate logische Teile erkennen können, aber sie sind viel stärker integriert. Bei einem MacBookPro müssen Sie die Hälfte des Laptops zerlegen, um die Tastatur zu reinigen. Und wenn Sie Ihren Kaffee auf einem Laptop verschütten, ist dies ein Grund, einen neuen Laptop zu bestellen. Keine neue Tasse Kaffee.


3. Erstellen Sie Ihre eigenen Klassen

Da Sie jedoch gerade erst das Programmieren lernen, sollten Sie klein anfangen und lernen, Ihre eigenen Klassen zu erstellen.

Natürlich haben Sie bereits Klassen erstellt, aber Sie müssen lernen, zu verstehen, welche Klassen in ein Programm aufgenommen werden sollten, wie sie benannt werden sollten und welche Methoden sie haben sollten. Und wie sie miteinander interagieren sollten.

Liste der Entitäten

Wenn Sie nicht wissen, wo Sie anfangen sollen, beginnen Sie von vorne.

Wenn Sie mit dem Entwerfen eines Programms beginnen, können Sie einfach ein Blatt Papier nehmen und eine Liste der Entitäten (Objekte) aufschreiben, die im Programm enthalten sein sollen. Und dann schreiben Sie Code nach dem Prinzip, dass jede Entität eine separate Klasse ist.

Beispiel

Nehmen wir an, Sie möchten ein Schachspiel schreiben. Sie benötigen die folgenden Elemente: ein Schachbrett und 6 Arten von Schachfiguren. Die Stücke bewegen sich auf unterschiedliche Weise und haben unterschiedliche Werte. Es macht Sinn, dass es sich um separate Klassen handelt. Tatsächlich gilt zu Beginn: Je mehr Kurse, desto besser.

Es ist sehr selten, einen unerfahrenen Programmierer zu treffen, der zehn statt zwei Kurse schreibt. Anstatt zehn Lektionen zu schreiben, schreiben Anfänger gerne zwei Lektionen oder vielleicht nur eine. Schreiben Sie also bitte mehr Kurse, meine Programmierkollegen. Und Ihr Code wird für alle klarer, außer vielleicht für Sie 😛

Schach

Angenommen, wir beschließen, Kurse für Schach zu schreiben: Wie würden diese Kurse aussehen?

Ist das Schachbrett nur eine 8 x 8-Anordnung? Es ist besser, eine separate Klasse zu erstellen, die intern einen Verweis auf ein Array speichert. Anschließend können Sie der Klasse „Schachbrett“ viele nützliche Methoden hinzufügen, um beispielsweise zu überprüfen, ob eine bestimmte Zelle leer oder belegt ist

Im Allgemeinen sollten Sie sich zu Beginn immer an diesem Grundsatz orientieren: Ein Programm hat verschiedene Entitäten und eine Entität hat einen Typ. Dieser Typ ist die Klasse.


4. Statische Variablen und Methoden

Vergessen Sie auch nicht, statische Variablen und Methoden zu verwenden. Wenn eine Schachfigur mit einer anderen auf dem Schachbrett interagiert, benötigt Ihr Code eine Methode, die Verweise auf die erste und zweite Figur sowie auf das Schachbrett entgegennimmt.

Statische Variablen, auf die von überall im Programm zugegriffen werden kann, werden normalerweise verwendet, um zu vermeiden, dass Verweise auf Objekte, die „immer existieren“, ständig weitergegeben werden.

Zum Beispiel so:

Code Notiz
public class ChessBoard
{
   public static ChessBoard board = new ChessBoard();
   public ChessItem[][] cells = new ChessItem[8][8];
   ...
}

public class Game
{
   public static void main(String[] args)
   {
      var board = ChessBoard.board;
      board.cells[0][3] = new King(Color.WHITE);
      board.cells[0][4] = new Queen(Color.WHITE);
      ...
   }
}


Ein Verweis auf ein einzelnes ChessBoardObjekt.
Ein zweidimensionales 8x8-Array, keine statische Variable.








Fügen Sie die Teile dem Brett hinzu.

Anstelle einer statischen Variablen können Sie auch eine Methode erstellen, die ein Singleton-Objekt zurückgibt. Zum Beispiel so:

public class ChessBoard
{
   private static ChessBoard board = new ChessBoard();
   public static ChessBoard getBoard()
   {
      return board;
   }

   public ChessItem[][] cells = new ChessItem[8][8];
   ...
}

public class Game
{
   public static void main(String[] args)
   {
      var board = ChessBoard.getBoard();
      board.cells[0][3] = new King(Color.WHITE);
      board.cells[0][4] = new Queen(Color.WHITE);
      ...
   }
}