Frage

    

Diese Frage bereits eine Antwort hier:

         

Im Moment arbeite ich an einem einfachen Spiel in Java mit mehreren verschiedenen Modi. Ich habe ein Hauptspielklasse erweitert die Hauptlogik in den anderen Klassen zu setzen. Trotzdem ist die Hauptspielklasse noch ziemlich heftige.

Nach einem kurzen Blick auf meinen Code nehmen die meisten war es Getter und Setter (60%) im Vergleich zu dem Rest, die wirklich für die Logik des Spiels benötigt wird.

Ein paar Google-Suchanfragen haben behauptet, dass Getter und Setter sind böse, andere haben behauptet, dass sie für eine gute OO Praxis und große Programme notwendig sind.

Also, was soll ich tun? Welche soll es sein? Soll ich meine Getter und Setter für meine privaten Variablen zu ändern, oder sollte ich sie halten?

War es hilfreich?

Lösung

Es gibt auch den Standpunkt, dass die meiste Zeit, Einrichter noch Kapselung bricht, indem Sie Werte festlegen, die bedeutungslos sind. Als sehr offensichtliches Beispiel, wenn Sie sich auf dem Spiel einen Punktezähler, die je nur nach oben geht, statt

// Game
private int score;
public void setScore(int score) { this.score = score; }
public int getScore() { return score; }
// Usage
game.setScore(game.getScore() + ENEMY_DESTROYED_SCORE);

es sollte

// Game
private int score;
public int getScore() { return score; }
public void addScore(int delta) { score += delta; }
// Usage
game.addScore(ENEMY_DESTROYED_SCORE);

Dies ist vielleicht ein bisschen ein facile Beispiel. Was ich versuche zu sagen, dass diskutieren Getter / Setter vs öffentliche Bereiche verschleiert oft größere Probleme mit Objekten jeweils anderen internen Zustand in intimer Weise zu manipulieren und damit zu eng gekoppelt sind.

Die Idee ist es, Methoden zu machen, die direkt Dinge tun, die Sie tun mögen. Ein Beispiel wäre, wie Feinde ‚lebendig‘ Status zu setzen. Sie könnten eine setAlive (boolean alive) Methode zu haben versucht sein. Stattdessen sollten Sie haben:

private boolean alive = true;
public boolean isAlive() { return alive; }
public void kill() { alive = false; }

Der Grund hierfür ist, dass, wenn Sie die Implementierung ändern, die Dinge nicht mehr einen „lebendig“ boolean haben, sondern einen „Trefferpunkte“ Wert, können Sie, dass rund ändern, ohne den Vertrag der beiden Methoden zu brechen Sie früher schrieben:

private int hp; // Set in constructor.
public boolean isAlive() { return hp > 0; } // Same method signature.
public void kill() { hp = 0; } // Same method signature.
public void damage(int damage) { hp -= damage; }

Andere Tipps

  • Sehr böse. Öffentliche Felder
  • Ein wenig böse. Getter und Setter, wo sie erforderlich sind nicht
  • Gute: Getter und Setter nur dort, wo sie wirklich erforderlich sind - die Art machen „größeres“ Verhalten aussetzen, die passieren verwenden seinen Zustand, und nicht nur die Art als Repository staatliche Behandlung zu durch andere Arten manipuliert werden.

Es hängt wirklich von der Situation, obwohl - manchmal Sie wirklich tut will nur ein stummes Datenobjekt

.

Sie haben schon viele gute Antworten auf diese, so dass ich nur meine zwei Cent geben. Getter und Setter sind sehr, sehr böse. Sie im Wesentlichen können Sie so tun, als Ihr Objekt Interna zu verstecken, wenn die meiste Zeit alles, was Sie getan haben, ist in redundanten Code geworfen, die nichts tut, um einen internen Zustand zu verbergen. Für eine einfache POJO, gibt es keinen Grund, warum getName () und setName () kann nicht mit obj.name = „Tom“ ersetzt werden.

Wenn der Aufruf der Methode lediglich Zuweisung ersetzt, dann alles, was Sie durch bevorzugen den Methodenaufruf gewonnen habe, ist Code aufblasen. Leider hat sich die Sprache die Verwendung von Getter und Setter in der Java Beans-Spezifikation verankert, so sind Java-Programmierer gezwungen, sie zu benutzen, auch wenn dabei überhaupt keinen Sinn macht.

Zum Glück Eclipse (und wahrscheinlich auch andere IDEs) können Sie sie automatisch generieren. Und für ein Spaß-Projekt, baute ich einmal einen Code-Generator für sie in XSLT. Aber wenn es eine Sache ist, würde ich loswerden in Java, es ist die übermäßige Abhängigkeit von Getter und Setter.

Getter und Setter erzwingen das Konzept der Kapselung in der objektorientierten Programmierung.

Durch die Zustände des Objekts mit von der Außenwelt verborgen, ist das Objekt wirklich verantwortlich für sich selbst, und nicht in einer Weise verändert werden kann, die nicht vorgesehen sind. Die einzigen Möglichkeiten, kann das Objekt manipuliert werden sind durch freiliegende öffentliche Methoden, wie Getter und Setter.

Es gibt einige Vorteile für die Getter und Setter mit:

1. zukünftige Änderungen ohne Änderung Code ermöglicht, dass die modifizierte Klasse verwendet.

Einer der großen Vorteile eines Getter und Setter ist, dass, wenn die öffentlichen Methoden definiert und es kommt eine Zeit, wenn die zugrunde liegende Implementierung geändert werden muss (zB einen Fehler zu finden, die behoben werden muss, einen anderen Algorithmus zur Verbesserung der Leistung, etc.), durch die Getter und Setter mit dem einzigen Weg, um das Objekt zu manipulieren, wird es dort vorhandene Code ermöglichen, nicht zu zerbrechen, und Arbeit als auch nach der Änderung erwartet.

Zum Beispiel, lassen Sie uns sagen, dass es ein setValue Verfahren, das die value private Variable in einem Objekt setzt:

public void setValue(int value)
{
    this.value = value;
}

Aber dann gab es eine neue Anforderung, die den Überblick über die Anzahl zu halten benötigte Mal value geändert wurde. Mit den Setter an Ort und Stelle ist die Änderung ziemlich trivial:

public void setValue(int value)
{
    this.value = value;
    count++;
}

Wenn das value Feld öffentlich waren, gibt es keine einfache Möglichkeit, später wieder zu kommen und einen Zähler hinzu, dass der Wert der die Anzahl von Malen hält geändert wurde. Daher sind mit Getter und Setter ein Weg, um „zukunftssicher“ die Klasse für Änderungen, die später kommen kann.

2. Erzwingen die Mittel, mit denen das Objekt manipuliert werden.

Eine weitere Möglichkeit, Getter und Setter nützlich sein, ist es, die Möglichkeiten zur Durchsetzung des Gegenstand kann daher manipuliert wird, ist das Objekt in der Kontrolle über seinen eigenen Zustand. Mit öffentlichen Variablen eines Objekts ausgesetzt, kann es leicht beschädigt werden.

Zum Beispiel kann ein ImmutableArray Objekt enthält einen int Array namens myArray. Wenn das Array ein öffentliches Feld ist, es wird nur nicht unveränderlich sein:

ImmutableArray a = new ImmutableArray();
int[] b = a.myArray;
b[0] = 10;      // Oops, the ImmutableArray a's contents have been changed.

einen wirklich unveränderlich Array zu implementieren, ein Getter für das Array (getArray Methode) geschrieben werden soll, so dass es eine Kopie seiner Array zurück:

public int[] getArray()
{
    return myArray.clone();
}

Und selbst wenn die folgenden Ereignisse eintritt:

ImmutableArray a = new ImmutableArray();
int[] b = a.getArray();
b[0] = 10;      // No problem, only the copy of the array is affected.

Die ImmutableArray ist in der Tat unveränderlich. die Variablen eines Objekt freilegen wird es ermöglichen, in einer Weise manipuliert werden, die nicht dazu bestimmt ist, sondern nur bestimmte Arten (Getter und Setter) ausgesetzt wird, kann das Objekt in beabsichtigter Weise manipuliert werden.

Ich nehme an, die Getter und Setter würden für Klassen wichtiger sein, den Teil einer API, die von anderen benutzt werden wird, wie es hält die API intakt und unverändert erlaubt, während Veränderungen in der zugrunde liegenden Implementierung ermöglicht.

Mit allen Vorteilen von Getter und Setter sagte, wenn der Getter lediglich den Wert der privaten Variable Rückkehr und die Setter lediglich einen Wert zu übernehmen und es zu einer privaten Variablen zugewiesen wird, so scheint es, die Getter und Setter sind nur Fremd und wirklich eine Verschwendung. Wenn die Klasse nur für die interne Verwendung durch eine Anwendung sein wird, die nicht von anderen benutzt werden wird, unter Verwendung von Getter und Setter extensiv nicht so wichtig sein, wie wenn eine öffentliche API zu schreiben.

Sie sind absolut böse.

@coobird leider absolut sie nicht „das Konzept der Kapselung erzwingen“, alles, was sie tun ist, Sie denken, Sie Daten einkapseln, wenn in der Tat sind Sie Daten über eine Eigenschaft mit Wahn Methode Pracht auszusetzen. Alles, was ein Getter / Setter macht ein öffentliches Feld tut besser.

die Anzahl der Methoden zur Reduzierung des Client watet durch und macht es kognitiv einfacher für die Kunden zu ändern, es ist Wert von zB

Erstens, wenn Sie öffentliche Daten wollen, es öffentlich machen, den Getter & Setter-Methoden loszuwerden.

object.field = value;

statt der kognitiv intensiv

object.setField(value);

, wo der Kunde nun die Getter / Setter-Methode überprüfen muß, um zu sehen, ob es irgendwelche Nebenwirkungen hat.

Zweitens, wenn Sie wirklich etwas anderes in der Methode müssen tun, warum nennt es eine get / set-Methode, wenn es mehr Aufgaben als nur bekommen oder Einstellung hat? Entweder folgen dem SRP oder die Methode etwas nennen, die Sie tatsächlich sagt, was die ganze Methode funktioniert wie Zarkonnen die Beispiele, die er erwähnt zB.

public void kill(){
    isAlive = false;
    removeFromWorld(this);
}

statt

public void setAlive(boolean isAlive){
    this.isAlive = isAlive;
    if (isAlive)
        addToWorld(this);
    else
        removeFromWorld(this);
}

Dabei hat die setAlive (boolean) -Methode dem Client sagen, dass als Nebeneffekt, es wird das Objekt aus der Welt entfernen? Warum sollte der Kunde keine Kenntnis über das IsAlive Feld? Plus, was passiert, wenn das Objekt in der Welt erneut hinzugefügt, sollte es erneut initialisiert werden? warum sollte der Kunde kümmern sich um irgendetwas davon?

IMHO die Moral ist zu nennen Methoden genau zu sagen, was sie tun, folgen Sie der SRP und loszuwerden Getter / Setter. Wenn es Probleme ohne Getter / Setter ist, Objekte erzählen ihre eigene schmutzige Arbeit innerhalb ihrer eigenen Klasse zu tun, anstatt zu versuchen, die Dinge mit ihnen in anderen Klassen zu tun.

hier endeth meine rant, traurig über das,)

Es ist ein rutschiger Abhang.

Ein einfaches Transferobjekt (oder Parameter-Objekt) kann den alleinigen Zweck hat einige Felder halten und ihre Werte auf Anfrage bereitstellt. Man könnte jedoch auch in diesem degenerierten Fall argumentieren, dass das Objekt unveränderlich sein sollte -. konfigurierte im Konstruktor und das Aussetzen nur get ... Methoden

Es gibt auch den Fall einer Klasse, die einige „Bedienknöpfe“ aussetzt; Ihr Autoradio UI wahrscheinlich als Belichtungs etwas wie getVolume, setVolume, getChannel und setChannel, aber seine eigentliche Funktionalität empfängt Signale und abstrahlen zu verstehen. Aber diese Knöpfe setzen nicht viel Implementierungsdetail; Sie nicht von den Schnittstellenfunktionen, ob der Funk Transistoren ist, meist-Software oder Vakuumröhren.

Je mehr Sie beginnen ein Objekt als aktiven Teilnehmer in einer Problemdomäne Aufgabe zu denken, je mehr man in Begriffen denken würde es zu fragen, zu etwas tun , anstatt sich zu fragen, zu sagen, Sie seinen internen Zustand, oder es für seine Daten so anderer Code fragt kann mit diesen Werten etwas tun.

So ... "böse"? Nicht wirklich. Aber jedes Mal, wenn Sie geneigt sind in einem Wert zu setzen und sowohl get aussetzen ... und set ... Methoden auf diesem Wert, fragen Sie sich, warum, und was dieses Objekt reponsibility wirklich ist. Wenn die einzige Antwort, die Sie selbst geben können, ist: „Um diesen Wert für mich halten“, dann vielleicht etwas anderes als OO hier vor sich geht.

Ihre Spielklasse folgt wahrscheinlich der Gott Objekt Antipattern, wenn es so viele Variablen aussetzt. Es ist nichts falsch mit Getter und Setter (obwohl ihre Ausführlichkeit in Java ein bisschen lästig sein kann); in einem gut gestalteten app, wo jede Klasse eine klar getrennten Funktionen hat, werden Sie nicht Dutzende von ihnen in einer einzigen Klasse benötigen.

Edit: Wenn der Hauptpunkt für die Getter und Setter ist auf „Konfigurieren“ das Spiel classe (Ich verstehe Ihre Bemerkung, dass Art und Weise), dann wahrscheinlich die Getter nicht braucht (es ist perfekt Geldstrafe für eine Klasse über einen eigenen Variablen zuzugreifen, ohne get-Methoden) zu verwenden und Sie können sich wahrscheinlich viele der Setter in „Gruppe Setter“, die mehrere Variablen gesetzt, die zusammen konzeptionell gehören kollabieren.

Die Anwesenheit von Getter und Setter neigt zu zeigen (einen „Geruch“, wenn Sie in diese Art der Grundschule Sprache sind), dass es ein Design-Problem. Trivial Getter und Setter sind kaum zu unterscheiden von den öffentlichen Bereichen. Typischerweise in einer anderen Klasse des Code auf den Daten Betrieb sein wird -. Schlechte Kapselung, und was würden Sie von Programmierern nicht wohl mit OO erwarten

In einigen Fällen Getter und Setter sind in Ordnung. Aber in der Regel eine Art sowohl mit Getter und Setter zeigt Design-Probleme. Getter arbeiten für Unveränderlichkeit; Setter arbeiten für „sagen nicht fragen“. Sowohl Unveränderlichkeit und „sagen, nicht fragen,“ sind gute Design-Entscheidungen, solange sie nicht in einem überlappenden Stil angewendet werden.

Meine Meinung ist, dass Getter und Setter eine Voraussetzung für gute Programme sind. Stick mit ihnen, aber nicht schreibt unnötige Getter / Setter -. Es direkt mit allen Variablen nicht immer notwendig ist, zu behandeln

Ich glaube nicht wirklich, dass sie böse sind. Aber ich würde gerne in einer Welt zu leben, wo ich nie, sie zu benutzen, es sei denn hatte ich wirklich gebraucht zu.

Ein Beispiel, das ich oben gelesen wurde Ihr Code future-proofing. Zum Beispiel:

public void setValue(int value)
{
    this.value = value;
}

Dann ändern sich die Anforderungen, und Sie müssen verfolgen, wie oft der Wert festgelegt wurde.

So:

public void setValue(int value)
{
    this.value = value;
    count++;
}

Das ist schön. Ich verstehe es. Doch in Ruby, würde die folgenden nicht dem gleichen Zweck dienen?

someobject.my_value = 100

Später, müssen Sie die Anzahl der Male my_value verfolgen gesetzt wurde. Na, dann könnte man nicht einfach überschreiben die Setter DANN und nur DANN

def my_value=(value)
    @my_value = value
    @count++
end

Ich bin für schöne Code, aber ich muss zugeben, auf der Suche durch die Berge von Java-Klassen und wir haben buchstäblich tausende von Codezeilen zu sehen, die nichts anderes sind als grundlegende Getter / Setter ist hässlich und störend.

Als ich die Entwicklung in C # in Vollzeit, haben wir öffentliche Eigenschaften die ganze Zeit und haben individuelle Getter / Setter nur bei Bedarf. Arbeitete wie ein Charme, und es hat nichts kaputt machen.

Wie immer die einzige Antwort ist: Es hängt davon ab. Wenn Sie die einzigen Peron berühren den Code sind, können Sie tun, was Sie bequem mit, einschließlich der Einnahme Verknüpfungen.

Einer der Vorteile von Setter ist, dass Kontrollen müssen in Ihrem Code nur an einer Stelle durchgeführt werden.

Sie möchten vielleicht etwas mehr Aufmerksamkeit zu zahlen, was tatsächlich durch diese Verfahren zu erhalten und eingestellt wird. Wenn Sie mit ihnen den Zugriff auf konstante Werte zu schaffen, sind Sie wahrscheinlich besser durch Konstanten verwenden.

Dies ist abhängig von der Programmiersprache, in Frage. Ihre Frage wird im Rahmen von Java gerahmt, wo es, dass im Allgemeinen Getter und Setter scheint sind gedacht als eine gute Sache.

Im Gegensatz dazu ist in der Python-Welt, werden sie als schlechter Stil allgemein betrachtet: sie fügen Linien auf den Code ohne Funktionalität tatsächlich hinzugefügt wird. Wenn Python-Programmierer benötigen, können sie metaprogramming verwenden zu fangen bekommen und / oder Einstellung von Objektattributen.

In Java (zumindest die Version von Java habe ich gelernt, etwas vor zehn Jahren), war das nicht möglich. So wird in Java ist es in der Regel am besten religiös Getter und Setter zu verwenden, so dass, wenn Sie benötigen, erhalten Sie Zugriff auf die Variablen außer Kraft setzen können.

(Dies gilt nicht Python unbedingt besser machen als Java, nur anders.)

Just FYI: Neben all den hervorragenden Antworten in diesem Thread, denken Sie daran, dass alle Gründe, die Sie mit für oder gegen Getter / Setter kommen kann, ist die Leistung ein nicht (wie manche glauben). Die JVM ist intelligent genug, um trivial Getter / Setter (auch Nicht-final diejenigen, solange sie nicht tatsächlich überschrieben) inline.

Sie können einige Ihrer Klassen von Wertklassen ersetzen. Dies ermöglicht Ihnen, den Getter und vermeiden Probleme zu entfernen, wenn der Inhalt von unter Ihnen geändert wird.

Wenn Sie den externen Zugriff auf einzelne Werte von Feldern, die Verwendung Getter und / oder Setter. Wenn nicht, nicht. Verwenden Sie niemals den öffentlichen Bereichen. So einfach ist das! (Ok, es ist nie , die einfach, aber es ist eine gute Daumenregel).

Generell sollte man auch feststellen, dass Sie benötigen einen Setter viel seltener als ein Getter liefern - vor allem, wenn Sie versuchen, Ihre Objekte unveränderlich zu machen - was eine gute Sache ist (aber nicht immer die beste Wahl) - aber auch wenn nicht.

Ich habe vor für einige Monate in Java-Programmierung worden, und ich habe gelernt, dass wir Getter & Setter nur verwenden sollten, wenn es für die Anwendung erforderlich ist

hat Spaß:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top