Path: csiph.com!fu-berlin.de!news-ailanthus.fernuni-hagen.de!news.fernuni-hagen.de!.POSTED!not-for-mail From: Michael Paap Newsgroups: de.comp.lang.java Subject: =?UTF-8?Q?Re:_Grunds=c3=a4tzliche_Frage_zu_Interfaces?= Date: Thu, 31 Dec 2015 02:35:24 +0100 Organization: FernUni Hagen Lines: 115 Message-ID: <5684865C.7090405@mpaap.de> References: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Trace: news-ailanthus.fernuni-hagen.de 1451525725 4928 b0a88f30408c6d7762de8cd1472a8030 (31 Dec 2015 01:35:25 GMT) X-Complaints-To: newsadmin@fernuni-hagen.de NNTP-Posting-Date: Thu, 31 Dec 2015 01:35:25 +0000 (UTC) User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:38.0) Gecko/20100101 Thunderbird/38.5.0 To: "Ralf S. Hellersen" In-Reply-To: X-Enigmail-Draft-Status: N1110 Xref: csiph.com de.comp.lang.java:12883 Am 31.12.2015 um 00:09 schrieb Ralf S. Hellersen: >> Dieses Bilden eines "Teil-Typs" ermöglicht es, dass Programmteile völlig >> unabhängig von konkreten Implementierungen gebaut werden können: Eine >> Klasse, welche ein Objekt nur in seiner Rolle als Exemplar eines >> Interface-Typs kennt, ist von der tatsächlichen Klasse dieses Objekts >> unabhängig und kann vollständig gebaut und übersetzt werden, ohne dass >> es überhaupt schon eine das Interface implementierende Klasse geben >> muss. Und das ist eine wesentliche Voraussetzung z.B. für das Schreiben >> von Frameworks und generell für eine team- oder gar >> unternehmensübergreifend arbeitsteilige Entwicklung. > Dafür werde ich nach Beispielen suchen, um es zu verstehen. Hier mal ein simples Beispiel... ein TicTacToe-Spiel. Wenn ich dir folgende Klassen gebe: public enum EFieldState { CROSS, CIRCLE, EMPTY } public class PlayerException extends Exception { public PlayerException(String message, Throwable cause) { super(message, cause); } public PlayerException(String message) { super(message); } } und ein paar Interfaces festlege: public interface ITTTModel { EFieldState getFieldState(int row, int column); void setFieldState(int row, int column, EFieldState state); EFieldState[][] getFieldStates(); } public interface ITTTView { void refresh(); } public interface IPlayer { Point getMove(EFieldState[][] situation) throws PlayerException; } public interface IRuleMaster { boolean isValidMove(Point move, EFieldState newState); } dann kannst du schon eine hübsche kleine Partie-Steuerung bauen, die völlig unabhängig davon ist, woher konkrete Player-Klassen später ihre Züge bekommen werden (von einem Menschen vorm Rechner, übers Netzwerk, einer KI...), wie das Model intern implementiert ist (ein String, ein 3x3-Array, Datenbankzugriff...) oder wie das Spielfeld "ausgegeben" wird (grafische Darstellung, ASCII auf Konsole, Sprachausgabe, Braillezeile). Mal als "Skizze": public class MatchController { private IPlayer player1; private IPlayer player2; private ITTTModel model; private ITTTView view; private IRuleMaster ruleMaster; public MatchController(IPlayer player1, IPlayer player2, ITTTModel model, ITTTView view, IRuleMaster ruleMaster) { this.player1 = player1; this.player2 = player2; this.model = model; this.view = view; this.ruleMaster = ruleMaster; } @Override public void run() { for (int i = 0; i < 9; i++) { boolean even = i % 2 == 0; IPlayer currentPlayer = even ? player1 : player2; EFieldState nextFieldState = even ? EFieldState.CROSS : EFieldState.CIRCLE; boolean moved = false; try { while (!moved) { Point move = currentPlayer. getMove(model.getFieldStates()); if (ruleMaster.isValidMove(move, nextFieldState)) { model.setFieldState( move.x, move.y, nextFieldState); view.refresh(); moved = true; } else { // Problembehandlung } } } catch (PlayerException e) { // Exceptionhandling } } } } Das Bauen der Klassen, welche die Interfaces implementieren, können derweil andere Mitarbeiter erledigen. ;-) Gruß, Michael