Packages, package Modifier,
und das import Keyword

Mit dem Laden des Videos akzeptierst du die Datenschutzerklärung von YouTube. Wenn du die Menge an Daten reduzieren möchtest, die YouTube von dir sammelt, solltest du dich vorher aus deinem YouTube-Account ausloggen, das Speichern von Cookies für das Google-Ads-Programm deaktivieren und/oder Cookies im Browser blockieren.
YouTube immer automatisch ladenInhaltsverzeichnis
Als Text lesen
Jetzt wo du mit einer richtigen IDE programmierst, hast du genug Platz um mehr als nur eine Klasse zu erstellen. In Java sollte nämlich (bis auf wenige Ausnahmen) jede Klasse in einer eigenen .java Datei liegen. Diese muss genauso heißen wie die Klasse selbst, also z.B. Calculator.java für die Klasse Calculator
.
Ich denke du glaubst mir wenn ich dir sage, dass es bei großen Softwareprojekten seeehr viele Klassen und damit ebenso viele Dateien geben kann. Was aber, wenn mehrere dieser Klassen einen identischen Namen haben?
Um dieses Problem zu lösen, und um dem Projekt eine gute Struktur zu geben, gibt es Packages.
Packages sind Ordner, in denen .java Dateien liegen, und werden verwendet um zusammengehörende Klassen zu gruppieren. Wenn eine Klasse in einem anderen Package liegt als dem default Package, muss dies mit dem package
Keyword explizit deklariert werden:
In IntelliJ kannst du ein neues Package über Rechtsklick auf src Ordner > New > Package erstellen.
Wenn nun in einer Klasse ein Objekt einer anderen Klasse verwendet wird, muss dem Compiler zuerst mitgeteilt werden, in welcher Datei sich diese Klasse befindet. Hierfür gibt es das import
Keyword:
Noch eine Sache
Du kennst schon die Access modifier private
und public
. Was aber, wenn du (wie zu Beginn dieses Kurses) gar keinen Access Modifier vor Attributen bzw. Methoden verwendest?
Der package private Modifier (oder auch default Modifier) wird implizit immer dann verwendet, wenn kein konkreter Access Modifier angegeben wurde.
Attribute und Methoden, die package private sind, sind nur innerhalb des eigenen Packages sichtbar. Für Klassen innerhalb des Packages verhält sich dieser also wie public
, für Klassen außerhalb wie private
.
Modifier | private |
package (kein Modifier) | public |
---|---|---|---|
Zugriff aus eigener Klasse | ✔ | ✔ | ✔ |
Zugriff aus eigenem Package | ❌ | ✔ | ✔ |
Zugriff aus anderen Packages | ❌ | ❌ | ✔ |
Du solltest in den allermeisten Fällen jedoch explizit private
oder public
als Modifier angeben.
Tic-Tac-Toe
Diese Übung wird ein bisschen größer als sonst. Dafür wirst du am Ende ein funktionierendes Tic-Tac-Toe Spiel für zwei Spieler programmiert haben.
Teil 1: Nutzereingabe
Bisher hast du immer nur Ausgaben auf der Konsole angezeigt. Wir wollen aber auch Nutzereingaben über diese entgegennehmen. Hierfür gibt es in der Java-Bibliothek die Klasse Scanner
des Packages java.util
. Du kannst beispielsweise mit der folgenden Methode readInt(String inputText)
eine Ganzzahl einlesen:
Aufgaben
- Erstelle ein neues Java Projekt
- Erstelle eine neue Klasse
UserInput
im Packagetictactoe.input
und füge den Code von oben ein - Importiere
Scanner
aus dem Packagejava.util
Teil 2: Spielfeld
Wir benötigen ein Spielfeld. Bei Tic-Tac-Toe ist das ein 3 x 3 Gitter aus einzelnen Feldern, die entweder leer (' '
) sind oder von einem Spieler gesetzt wurden ('X'
/ 'O'
). Wir modellieren dieses Spielfeld mit einer neuen Klasse, die ein 9-elementiges char
Array enthält.
Erstelle eine Klasse GameGrid
im Package tictactoe.grid
und implementiere die folgenden Programmteile:
- Ein Objektattribut
content
, das einchar
Array ist und später speichert, welche Felder von welchem Spieler belegt sind. Index 0 soll hierbei die obere linke Ecke sein, Index 8 die untere rechte. - Ein Konstruktor, der
content
mit 9 Leerzeichen initialisiert - Eine Methode
void set(int position, char value)
, die das Feld an Positionposition
mit dem Wertvalue
füllt (Du kannst davon ausgehen, dassposition
ein valider Index ist) - Eine Methode
boolean freePosition(int position)
, die genau danntrue
zurückgibt, wennposition
ein gültiger Index fürcontent
ist, und das Feld an diesem Index leer ist - Eine Methode
boolean full()
, die genau danntrue
zurückgibt, wenn alle Felder durch einen Spieler gesetzt wurden, also keines mehr leer ist -
Eine Methode
void printToConsole()
, die zuerst eine Leerzeile auf der Konsole ausgibt, und anschließend das Spielfeld in folgender Form (Beispiel):O | | ---|---|--- O | X | ---|---|--- | | X
- Eine Methode
boolean won()
, die genau danntrue
zurückgibt, wenn ein Spieler gewonnen hat (egal welcher). Das ist der Fall, wenn eine Zeile, eine Spalte, oder eine Diagonale nur noch aus'X'
bzw.'O'
besteht.
Teil 3: Das Eigentliche Spiel
Lass uns nun das eigentliche Spiel zusammenbauen:
- Erstelle eine Klasse
TicTacToe
im Packagetictactoe
- Erstelle die Objektattribute
GameGrid gameGrid
undUserInput userInput
, die in einem parameterlosen Konstruktor instanziiert werden - Erstelle eine Methode
int readValidPosition(char currentPlayer)
, die eine vom Nutzer eingegebene Spielfeld-Position zurückgibt. Falls diese jedoch kein gültiger Index ist oder das Feld bereits belegt ist, soll der Vorgang wiederholt werden, bis eine korrekte Eingabe vorliegt -
Erstelle eine Methode
void gameLoop()
, die vom Konstruktor aufgerufen wird und den Spielablauf steuert. Dieser ist folgendermaßen:- Das Spielfeld wird vor jedem Zug auf der Konsole ausgegeben
- Spieler X beginnt
- Nach jedem Zug ist der jeweils andere Spieler an der Reihe
- Hat ein Spieler gewonnen, so ist das Spiel beendet. Es soll ausgegeben werden, wer der Gewinner ist
- Sind alle 9 Felder belegt und kein Spieler hat gewonnen, ist das Spiel unentschieden und endet
- Erstelle eine
main
Funktion, die den Konstruktor aufruft
Denk daran, dass du die Methoden der anderen Klassen nicht zum Spaß implementiert hast!
Fertig!
Teste dein Spiel, ob alles so funktioniert wie erwartet. Vermutlich musst du noch einige Fehler suchen und beheben.
Häufige Fehlerquellen
Missing package statement
: Du musst in jeder Klasse angeben, in welchem Package diese sich befindetCannot resolve symbol 'Xyz'
: Der Import fürXyz
fehlt- Es passiert nichts: Ruft
main
den Konstruktor auf? Ruft der KonstruktorgameLoop()
auf? - Das Spiel endet sofort nach dem ersten Zug: Gibt deine
won()
Methode nurtrue
zurück, wenn die Felder nicht leer sind? 'xyz()' has private access in 'Abc'
Methoden inAbc
sind nichtpublic