Warum erfordern Schnittstellen Methoden gegenüber Mitgliedern?

8

... Da dies uns zwingt, Getter und Setter zu schaffen, die in der Praxis oft völlig fremd sind? Gibt es einen guten Grund für das Sprachdesign, warum Schnittstellen in den meisten (allen?) Sprachen es Mitgliedsfeldern nicht erlauben, die Schnittstellenspezifikation zu erfüllen?

In den meisten vorhandenen Sprachen werden Mitglieder grundlegend anders behandelt als Methoden. MUSS dies jedoch der Fall sein? In einer theoretischen Sprache konnten wir keine Schnittstelle haben, die (a) eine Null-Argument-Methode als Getter spezifizierte, aber ein lesbares Mitglied als Implementierer akzeptierte und (b) eine Einzel-Arg-Methode als Setter spezifizierte, aber akzeptierte ein beschreibbares Mitgliedsfeld als Implementierer in einer Sprache, die die Angabe der direkten Zugriffssteuerung für Variablen unterstützt, wenn diese deklariert werden? Eine prototypische Sprache, die eine Mehrfachvererbung ermöglicht (um den sehr gültigen Punkt anzusprechen, den einige Befragte angesprochen haben), wäre ideal für so etwas.

Bitte informieren Sie mich, wenn so etwas bereits existiert.

Ingenieur
quelle
2
Äh ... Methoden sind Mitglieder. Ich nehme an, Sie meinen "Mitgliedsfelder"?
Aaronaught
OK, um die richtige Java-Terminologie zu verwenden, ja, "Mitgliedsfelder". Vielen Dank für den Hinweis.
Ingenieur
1
OOP ist scheiße, aber versuchen Sie es mit C #, wenn Sie müssen.
Job

Antworten:

3

Offensichtlich werden Mitglieder in den meisten vorhandenen Sprachen grundlegend anders behandelt als Methoden. MUSS dies jedoch der Fall sein?

Nicht aus irgendeinem theoretisch begründeten Grund. Ich denke, die Gründe, warum Sie es nicht oft sehen, sind praktisch:

Das erste ist, wie Sie zur Laufzeit mit diesen Dingen umgehen. In Java oder C ++ ist eine Zuweisung an ein primitiv typisiertes öffentliches Mitglied wie foo.x = 5einfach zu handhaben: Dinge 5in ein Register eintragen, herausfinden, wo sich das xMitglied im Speicher befindet, foound das Register dort ablegen. In einer Sprache wie C #, in der Klassen abfangende Zuweisungen an Mitglieder kapseln oder vorab berechnen können, wie diese Mitglieder bewerten , hat der Compiler kein a prioriWissen, ob die Implementierung einer zur Laufzeit zur Verfügung gestellten Klasse diese Funktion verwendet. Das bedeutet, dass alle Zuweisungen und Bewertungen von öffentlichen Mitgliedern von öffentlichen Mitgliedern auf die Implementierung verschoben werden müssen. * Vorgänge, bei denen viel Zugriff auf diese Mitglieder besteht, werden am Ende beeinträchtigt, da sie ständig Unterprogrammaufrufe ausführen, die mit regulären Eingriffen schneller erledigt werden könnten Inline-Zuweisungen. Wenn Evaluierung und Zuordnung von Gettern und Setzern getrennt bleiben, kann der Entwickler steuern, wie er in einer bestimmten Situation behandelt wird.

Der zweite ist das Alter. Mit der möglichen Ausnahme von F # ist keine der heute sehr weit verbreiteten Sprachen jünger als ein Jahrzehnt, und selbst damals waren die zusätzlichen Zyklen, die erforderlich waren, um eine abgefangene Bewertung und Zuweisung zu ermöglichen, möglicherweise nicht akzeptabel.

Drittens ist Trägheit. Ich denke, bis zu einem gewissen Grad ist immer noch ein Stigma damit verbunden, öffentliche Mitglieder direkt zu beauftragen, selbst wenn die Sprache es der Klasse erlaubt, sie zu manipulieren, und die Leute immer noch denken, dass Getter und Setter besser sind. Das wird mit der Zeit nachlassen, genau wie bei allen Menschen, die ihre Nasen in der Luft hatten, gegenüber Menschen, die Programme in höheren Sprachen geschrieben haben, anstatt sich zu versammeln.


* Damit ist ein Kompromiss verbunden: Eine Sprache muss es schwer haben, Auswertungen / Zuweisungen an die Klasse zu verschieben oder zur Laufzeit zu blockieren, wenn Code, der Inline-Auswertungen / Zuweisungen für eine bestimmte Klasse verwendet, versucht, eine Verknüpfung mit einer Implementierung herzustellen, die sie abfängt . Persönlich halte ich letzteres für eine schlechte Idee, da es die Neukompilierung von Code erzwingt, der eine unveränderte API verwendet.

Blrfl
quelle
Vielen Dank, Sie haben den Kern meiner Frage verstanden und sind auf die Details von WARUM eingegangen. Ich hatte die Vermutung, dass Geschwindigkeit einer der Gründe sein würde - wie immer, wenn Sie den Weg der "dynamischeren" Straße gehen. Wie wir jetzt bei Sprachen wie JS und Python sehen, übertrifft Flexibilität häufig die Geschwindigkeit, sodass sich die von Ihnen erwähnte "Trägheit" gegenüber bestimmten Sprachdesign-Trends, die auf (was früher notwendig war) Optimierung erwähnt, langsam auflöst.
Ingenieur
F # basiert stark auf Objective CAML - es ist vielleicht jünger als ein Jahrzehnt, aber die meisten (wahrscheinlich alle) Ideen sind älter.
Steve314
1
Ich bin ein bisschen neugierig, warum die beiden Downvoter den roten Knopf gedrückt haben.
Blrfl
@Blrfl: Mein Kritikpunkt wäre, dass sich Ihre Antwort zu sehr auf Implementierungsdetails konzentriert, anstatt sie aus Sicht des Sprachdesigns zu betrachten. Ich habe dich zwar nicht dafür herabgestimmt, aber vielleicht haben es andere.
Niels van der Rest
Scala ist auch relativ jung und weit verbreitet
Anzeigename
10

In den meisten vorhandenen Sprachen werden Mitgliedsfelder grundlegend anders behandelt als Methoden. MUSS dies jedoch der Fall sein?

Ja tut es.

Mitgliedsfelder sind Daten pro Instanz. Daten müssen tatsächlich für jede Instanz irgendwo im Speicher vorhanden sein - es muss eine Adresse oder eine Folge von Adressen dafür reserviert sein. In Java, .NET und vielen anderen OO-Sprachen werden diese Daten auf dem Heap gespeichert.

Methoden sind Daten pro Klasse. Sie sind Zeiger auf eine vtable. So erhalten Methoden einen virtuellen Versand. Pro Klasse ist nur eine Instanz zugeordnet.

Eine Schnittstelle ist im Wesentlichen ein spezieller Klassentyp, der nur Methoden und keine Instanzdaten enthält. Das ist Teil der Definition der Schnittstelle. Wenn es Daten enthalten würde, wäre es keine Schnittstelle mehr, sondern eine abstrakte Klasse. Diese beiden Optionen sind natürlich in Ordnung, je nachdem, welche Art von Entwurfsmuster Sie implementieren möchten. Wenn Sie jedoch Schnittstellen Instanzdaten hinzufügen, entfernen Sie alles, was sie zu Schnittstellen macht .

OK, warum kann eine Schnittstellenmethode nicht auf ein Mitgliedsfeld verweisen? Weil es auf Klassenebene nichts gibt, worauf man hinweisen könnte. Auch hier ist eine Schnittstelle nichts anderes als eine Methodentabelle. Der Compiler kann nur eine Tabelle generieren, und jede darin enthaltene Methode muss auf dieselbe Speicheradresse verweisen. Daher ist es für Schnittstellenmethoden unmöglich, auf Klassenfelder zu verweisen, da das Klassenfeld für jede Instanz eine andere Adresse ist.

Vielleicht könnte der Compiler dies trotzdem akzeptieren und eine Getter-Methode generieren, auf die die Schnittstelle verweist - aber dann wird das im Wesentlichen eine Eigenschaft . Wenn Sie wissen möchten, warum Java keine Eigenschaften hat, dann ist das eine wirklich lange und langwierige Geschichte, auf die ich hier lieber nicht eingehen möchte. Aber wenn Sie daran interessiert sind, möchten Sie vielleicht einen Blick auf andere OO Sprachen haben , die tun Eigenschaften implementieren, wie C # oder Delphi. Die Syntax ist wirklich einfach:

public interface IFoo
{
    int Bar { get; }
}

public class Foo : IFoo
{
    public int Bar { get; set; }
}

Ja, das ist alles was dazu gehört. Wichtig: Dies sind keine Felder, die "int Bar" in der FooKlasse ist eine Auto-Eigenschaft , und der Compiler macht genau das, was ich oben beschrieben habe: Automatische Generierung von Gettern und Setzern (sowie des Hintergrundelementfelds).

Um die Antwort auf Ihre Frage zusammenzufassen:

  • Schnittstellen erfordern Methoden , weil ihre gesamte Zweck ist nicht alle Daten enthalten;
  • Der Grund dafür, dass es keinen syntaktischen Zucker gibt , der es einer Klasse erleichtert, eine Schnittstelle zu implementieren, ist einfach, dass die Java-Designer dies nicht tun - und zu diesem Zeitpunkt ist die Abwärtskompatibilität ein Problem. Sprachdesigner treffen solche Entscheidungen. Sie müssen sich nur darum kümmern oder wechseln.
Aaronaught
quelle
Dies ist eine gute Antwort, insbesondere fand ich die Informationen zur Funktionssuche informativ. Vielen Dank.
Ingenieur
9

Dies ist ein Ergebnis des Ausblendens von Informationen, dh diese Mitglieder sollten nicht als Felder sichtbar sein, sondern als Eigenschaften, die lokal gespeichert / zwischengespeichert werden können oder nicht

Ein Beispiel ist der Hash-Code, der sich ändert, wenn sich das Objekt ändert. Daher ist es besser, ihn zu berechnen, wenn er angefordert wird, und nicht jedes Mal, wenn sich das Objekt ändert

Außerdem sind die meisten Sprachen Einzelvererbung + Mehrfachimplementierungen. Wenn Sie zulassen, dass Felder Teil von Schnittstellen sind, gelangen Sie in das Gebiet der Mehrfachvererbung (es fehlt nur die Standardimplementierung von Funktionen), das ein Minenfeld von Randfällen ist, um das Richtige zu tun

Ratschenfreak
quelle
Hier geht es um mehrfach implementierende Felder.
DeadMG
Ich muss sagen, wenn ich weiter darüber nachdenke, stimme ich der Mehrfachvererbung nicht wirklich zu. Ich frage mich wirklich, ob eine Darstellung von Datenelementen in Schnittstellen möglich ist und nicht, ob Sie Datenelemente zum Erstellen von Schnittstellen verwenden können (was im Wesentlichen eine abstrakte C ++ - Klasse ist). Da gibt es einen entscheidenden Unterschied.
Ingenieur
Es gibt wirklich kein Problem mit MI; Eine Sprache müsste nur zwei Schnittstellen mit widersprüchlichen Typen für dasselbe Mitglied implementieren.
Blrfl
6

Mitgliedsvariablen sind die Implementierung der Klasse, nicht die Schnittstelle. Möglicherweise möchten Sie die Implementierung ändern, sodass andere Klassen nicht direkt auf diese Implementierung verweisen dürfen.

Betrachten Sie eine Klasse mit den folgenden Methoden - C ++ - Syntax, aber das ist nicht wichtig ...

class example
{
  public:
    virtual void Set_Mode (int p_mode);
    virtual int  Mode () const;
};

Es scheint ziemlich offensichtlich, dass es eine Mitgliedsvariable namens modeoder m_modeähnlich geben wird, die diesen Moduswert direkt speichert und so ziemlich das tut, was eine "Eigenschaft" in einigen Sprachen tun würde - aber das muss nicht unbedingt wahr sein. Es gibt viele verschiedene Möglichkeiten, wie damit umgegangen werden kann. Zum Beispiel könnte die Set_Mode-Methode ...

  1. Identifizieren Sie den Modus mithilfe einer switch-Anweisung.
  2. Instanziieren Sie abhängig von diesem Moduswert eine Unterklasse einiger interner Klassen.
  3. Speichern Sie einen Zeiger auf diese Instanz als Mitgliedsvariable.

Danach können viele andere Methoden der Beispielklasse über den Zeiger geeignete Methoden dieser internen Klasse aufrufen und so ein modusspezifisches Verhalten erhalten, ohne den aktuellen Modus überprüfen zu müssen.

Der Punkt hier ist weniger, dass es mehr als einen möglichen Weg gibt, um solche Dinge zu implementieren, und viel mehr, dass Sie irgendwann Ihre Meinung ändern können. Vielleicht haben Sie mit einer einfachen Variablen begonnen, aber alle switch-Anweisungen zur Identifizierung des Modus in jeder Methode sind schmerzhaft. Oder vielleicht haben Sie mit der Instanzzeiger-Sache angefangen, aber das stellte sich als zu schwer für Ihre Situation heraus.

Es stellt sich heraus, dass solche Dinge für alle Mitgliedsdaten passieren können. Möglicherweise müssen Sie die Einheiten, in denen ein Wert gespeichert ist, von Meilen auf Kilometer ändern, oder Sie stellen möglicherweise fest, dass Ihre Aufzählung zur eindeutigen Identifizierung des Falls nicht mehr alle Fälle eindeutig identifizieren kann, ohne zusätzliche Informationen oder was auch immer zu berücksichtigen.

Dies kann auch für Methoden passieren - einige Methoden sind ausschließlich für den internen Gebrauch bestimmt, hängen von der Implementierung ab und sollten privat sein. Viele Methoden sind jedoch Teil der Schnittstelle und müssen nicht umbenannt werden oder was auch immer, nur weil die interne Implementierung der Klasse ersetzt wurde.

Wenn Ihre Implementierung verfügbar gemacht wird, hängt unweigerlich anderer Code davon ab, und Sie sind daran gebunden, diese Implementierung beizubehalten. Wenn Ihre Implementierung vor anderem Code verborgen ist, kann diese Situation nicht auftreten.

Das Blockieren des Zugriffs auf Implementierungsdetails wird als "Ausblenden von Daten" bezeichnet.

Steve314
quelle
"Code für eine Schnittstelle, keine Implementierung" ... Richtig. Manchmal kennen wir diese Dinge latent, aber es braucht jemanden, der sie so begründet, wie Sie es getan haben, um die Konzepte noch einmal wirklich zu festigen.
Ingenieur
Okay, warte eine Minute. Nach weiteren Überlegungen lesen Sie bitte meine Bearbeitung der Frage.
Ingenieur
Es ist etwas schwierig herauszufinden, was Ihre Bearbeitung war - aus irgendeinem Grund werden Unterschiede für einige der älteren Änderungen nicht angezeigt. Ich denke jedoch, dass Sie sagen: "Warum kann eine Eigenschaft keine Mitgliedsvariable als Standardimplementierung haben?" Eine Eigenschaft sieht (Schnittstelle) wie eine Mitgliedsvariable aus, wird jedoch über Getter / Setter-Methoden implementiert. Und IMO gibt es keinen Grund, warum diese Getter / Setter-Methoden standardmäßig kein Lesen / Schreiben in eine Mitgliedsvariable implementieren sollten - oder warum der Getter- und Setter-Aufruf nicht wegoptimiert werden sollte, wenn es sicher ist - und eine getrennte Vererbung zulassen Zusammenstellung usw.
Steve314
@Nick - Also ja, solange es möglich ist zu sagen "der Getter und / oder Setter für diese Eigenschaft sollte rein sein" oder "sollte nicht die Standardeinstellung sein" Ich denke, das ist eine gute Idee - etwas Unordnung für a zu beseitigen häufiger Fall mit Eigenschaften. Ich weiß nicht, ob es eine Sprache gibt, die dies bereits tut - habe selbst in Sprachen, in denen sie existieren, nicht viel Eigenschaften verwendet -, aber ich wäre überrascht, wenn dies nicht bereits unterstützt wird.
Steve314
3

Wie andere angemerkt haben, beschreibt eine Schnittstelle , was eine Klasse tut, nicht wie sie es tut. Es ist im Wesentlichen ein Vertrag, dem das Erben von Klassen entsprechen muss.

Was Sie beschreiben, ist etwas anders - eine Klasse, die eine Implementierung, aber möglicherweise nicht alle, als Form der Wiederverwendung bereitstellt . Diese werden allgemein als abstrakte Klassen bezeichnet und in einer Reihe von Sprachen (z. B. C ++ und Java) unterstützt. Diese Klassen können nicht eigenständig instanziiert werden, sondern nur von konkreten (oder weiteren abstrakten) Klassen geerbt werden.

Wie bereits erwähnt, sind abstrakte Klassen in Sprachen, die Mehrfachvererbung unterstützen, in der Regel von größtem Wert, da sie verwendet werden können, um einer größeren Klasse zusätzliche Funktionen bereitzustellen. Dies wird jedoch oft als schlechter Stil angesehen, da im Allgemeinen eine Aggregationsbeziehung ("has-a") angemessener wäre

Steve Mallam
quelle
Gute Antwort. Ich tendiere dazu, Komposition fast ausschließlich für die Art von Aufgaben zu bevorzugen, die ich heutzutage übernehme. Ich persönlich glaube nicht an die getrennte Behandlung von abstrakten Klassen und Schnittstellen in bestimmten Sprachen, wie andere in diesem Forum festgestellt haben. Obwohl es Gründe dafür gibt, sind diese Gründe im Allgemeinen auf grundlegende sprachliche Einschränkungen zurückzuführen (wie in meinem Kommentar erwähnt) auf die Antwort des Ratschenfreaks).
Ingenieur
1
Ich stimme Ihrem Kommentar zu: abstract / interfaces eher zu. Wenn ich auf alten Code zurückblicke, in dem ich viele abstrakte Klassen verwendet habe, ist mir mit 10-15 Jahren mehr Erfahrung klar, dass ich Sprachfunktionen verwendet habe, um schlechtes Design zu codieren
Steve Mallam
1

Bitte informieren Sie mich, wenn so etwas bereits existiert.

Objective-C-Eigenschaften bieten diese Art von Funktionalität mit ihren synthetisierten Eigenschaftenzugriffern. Eine Objective-C-Eigenschaft ist im Wesentlichen nur ein Versprechen, dass eine Klasse Accessoren bereitstellt, typischerweise in der Form foofür den Getter und setFoo:für den Setter. Die Eigenschaftsdeklaration gibt bestimmte Attribute der Accessoren an, die sich auf die Speicherverwaltung und das Threading-Verhalten beziehen. Es gibt auch eine @synthesizeDirektive, die den Compiler anweist, Accessoren und sogar die entsprechende Instanzvariable zu generieren, sodass Sie sich nicht die Mühe machen müssen, Getter und Setter zu schreiben oder für jede Eigenschaft einen ivar zu deklarieren. Es gibt auch syntaktischen Zucker, der den Zugriff auf Eigenschaften wie den Zugriff auf die Felder einer Struktur aussehen lässt, aber tatsächlich dazu führt, dass die Zugriffsberechtigten aufgerufen werden.

Das Ergebnis all dessen ist, dass ich eine Klasse mit Eigenschaften deklarieren kann:

@interface MyClass : NSObject
{}
@property (assign) int foo;
@property (copy) NSString *bar;
@end

und dann kann ich Code schreiben, der aussieht, als würde er direkt auf ivars zugreifen, aber tatsächlich Zugriffsmethoden verwenden:

MyClass *myObject = [[MyClass alloc] init];  // create myObject

// setters
myObject.foo = 127;                 // same as [myObject setFoo:127];
myObject.bar = @"Hello, world!";    // same as [myObject setBar:@"Hello, world!"];

// getters
int i = myObject.foo                // same as [myObject foo];
NSString *s = myObject.bar          // same as [myObject bar];

Es wurde bereits gesagt, dass Accessoren es Ihnen ermöglichen, die Schnittstelle von der Implementierung zu trennen, und der Grund, warum Sie dies tun möchten, besteht darin, Ihre Fähigkeit zu bewahren, die Implementierung in Zukunft zu ändern, ohne den Clientcode zu beeinflussen. Der Nachteil ist, dass Sie diszipliniert genug sein müssen, um Accessoren zu schreiben und zu verwenden, um Ihre zukünftigen Optionen offen zu halten. Objective-C macht das Generieren und Verwenden von Accessoren so einfach wie das direkte Verwenden von Ivars. In der Tat ist die Verwendung von Eigenschaften viel einfacher als der direkte Zugriff auf ivars, da sie einen Großteil der Arbeit der Speicherverwaltung erledigen. Und wenn die Zeit gekommen ist, in der Sie Ihre Implementierung ändern möchten, können Sie jederzeit Ihre eigenen Accessoren bereitstellen, anstatt sie vom Compiler für Sie generieren zu lassen.

Caleb
quelle
1

Warum erfordern Schnittstellen Methoden gegenüber Mitgliedern?

... Da dies uns zwingt, Getter und Setter zu schaffen, die in der Praxis oft völlig fremd sind? Gibt es einen guten Grund für das Sprachdesign, warum Schnittstellen in den meisten (allen?) Sprachen es Mitgliedern nicht ermöglichen, zur Erfüllung der Schnittstellenspezifikation beizutragen?

"Die meisten" Sprachen? Welche Sprachen haben Sie untersucht? In dynamischen Sprachen gibt es keine Schnittstellen. Es gibt nur drei oder vier statisch typisierte OO-Sprachen mit beliebiger Beliebtheit: Java, C #, Objective-C und C ++. C ++ hat keine Schnittstellen. Stattdessen verwenden wir abstrakte Klassen, und eine abstrakte Klasse kann ein öffentliches Datenelement enthalten. C # und Objective-C unterstützen beide Eigenschaften, sodass in diesen Sprachen keine Getter und Setter erforderlich sind. Das lässt nur Java. Vermutlich ist der einzige Grund, warum Java Eigenschaften nicht unterstützt, dass es schwierig war, sie abwärtskompatibel einzuführen.

Kevin Cline
quelle
Mitglieder sollten sich auf "Mitgliedsfelder" beziehen, im Gegensatz zu "Mitgliedsfunktionen", die ich einfach als Methoden bezeichne. Ich bin mir nicht sicher, aus welcher Sprache (falls vorhanden) ich diese Konvention aufgenommen habe. Angesichts dessen, was ich geschrieben habe, sehe ich Ihre Antwort, aber ich denke, ein Kommentar unter meiner Frage zur Klarstellung wäre konstruktiver gewesen.
Ingenieur
Zu C ++, touché. Tatsächlich gibt es jedoch Schnittstellen in dynamischen Sprachen, wobei JS und Python zwei sind, die sofort in den Sinn kommen. Ob ein Befürworter statisch typisierter Sprachen diese "Schnittstellen" nennen würde, ist eine ganz andere Diskussion, auf die ich keinen Sinn sehe. Persönlich bevorzuge ich kaum eine Seite dieses Zauns, da ich eine breite Palette von Sprachen für verschiedene Zwecke verwende.
Ingenieur
@ Nick: JS und Python haben Vererbung, aber ich würde nicht sagen, dass sie Schnittstellen haben; man kann jede Methode für jedes Objekt aufrufen.
Kevin Cline
1

In einigen Antworten werden "Ausblenden von Informationen" und "Implementierungsdetails" erwähnt, da Schnittstellenmethoden gegenüber Feldern bevorzugt werden. Ich denke, der Hauptgrund ist einfacher.

Schnittstellen sind eine Sprachfunktion, mit der Sie das Verhalten austauschen können, indem mehrere Klassen eine Schnittstelle implementieren. Das Verhalten einer Klasse wird durch ihre Methoden definiert. Felder hingegen spiegeln nur den Zustand eines Objekts wider .

Natürlich ist die Felder oder die Eigenschaften einer Klasse können Teil des Verhaltens sein, aber sie sind nicht der wichtigste Teil des durch die Schnittstelle definiert Vertrages; Sie sind nur ein Ergebnis. Aus diesem Grund können Sie beispielsweise mit C # Eigenschaften in einer Schnittstelle definieren, und in Java definieren Sie einen Getter in der Schnittstelle. Hier kommt ein bisschen verstecktes Informationsspiel ins Spiel, aber es ist nicht der Hauptpunkt.

Wie ich bereits sagte, können Sie mit Schnittstellen das Verhalten austauschen, aber schauen wir uns den Teil zum Austauschen an. Über eine Schnittstelle können Sie die zugrunde liegende Implementierung ändern, indem Sie eine neue Implementierungsklasse erstellen. Eine Schnittstelle, die aus Feldern besteht, macht also wenig Sinn, da Sie an der Implementierung von Feldern nicht viel ändern können.

Der einzige Grund, warum Sie eine Nur-Feld-Schnittstelle erstellen möchten, ist, wenn Sie sagen möchten, dass eine Klasse ein bestimmter Objekttyp ist. Ich habe das 'ist ein' Teil betont, weil Sie eher Vererbung als Schnittstellen verwenden sollten.


Randnotiz: Ich weiß, dass eine Komposition, die der Vererbung vorgezogen wird, normalerweise nur durch die Verwendung von Schnittstellen erreicht werden kann, aber die Verwendung von Schnittstellen, um eine Klasse mit einigen Eigenschaften zu "markieren", ist genauso schlecht. Die Vererbung ist bei sachgemäßer Verwendung großartig. Solange Sie sich an das Prinzip der Einzelverantwortung halten, sollten Sie keine Probleme haben.

Ich meine, ich habe zum Beispiel noch nie mit einer UI-Steuerungsbibliothek gearbeitet, die keine Vererbung verwendet. Der einzige Bereich, in dem Schnittstellen ins Spiel kommen, ist die Datenbereitstellung, z. B. ITableDataAdapterdas Binden von Daten an ein Tabellensteuerelement. Dies ist genau die Art von Dingen, für die Schnittstellen gedacht sind, um austauschbares Verhalten zu haben .

Niels van der Rest
quelle
0

In Java ist der Grund, dass Schnittstellen nur die Angabe von Methoden erlauben .

Wenn Sie also etwas mit einem Feld im Schnittstellenvertrag möchten, müssen Sie dies als Getter- und Setter-Methode tun.

Siehe auch diese Frage: Wann sind Getter und Setter gerechtfertigt?

Gemeinschaft
quelle
1
Vielen Dank für Ihre Antwort. Es war tatsächlich Ihre Antwort zu diesem Thema, die mich dazu brachte, diese Frage zu stellen :) Aber die Frage bleibt: "-WHY- haben sie nur Methoden zugelassen?" Bei Schnittstellen geht es nicht darum, Methoden anzugeben, das ist zyklische Logik. Der Punkt der Schnittstellen besteht darin, sicherzustellen, dass ein gewisser Basisgrad an Funktionalität erfüllt wird. Mitglieder können einen Teil dieser Funktionalität ausmachen. Warum also nicht zulassen, dass sie an der Schnittstellenerfüllung teilnehmen?
Ingenieur
Ich weiß nicht. Vielleicht, wenn Sie Gosling oder Steele direkt gefragt haben?
-1

Der Sinn einer Schnittstelle besteht darin, Funktionen anzugeben, die Sie implementieren müssen, um zu behaupten, diese Schnittstelle zu unterstützen.

Scott C Wilson
quelle
2
Dies beantwortet die Frage nicht. Die Frage ist, warum sie es so gemacht haben. Hatten Sie jemals darüber nachgedacht, nicht für jede Variable Getter und Setter zu schreiben und trotzdem eine Schnittstelle zu erfüllen? Das würde Zeit sparen!
Ingenieur
Sie fragen immer wieder nach Gettern und Setzern, und ich habe keine Ahnung warum. Schauen Sie sich eine einfache Oberfläche an: download.oracle.com/javase/6/docs/api/java/util/… Beachten Sie, dass es keine Getter und Setter gibt?
Scott C Wilson
1
Was beweist das? Beweist dieses eine Beispiel, dass Sie niemals einen einfachen / direkten Zugang zu Mitgliedern benötigen werden? Nein. Der Punkt ist, es ist albern, Wrap-Mitglieder in Getter / Setter als Teil der Schnittstelle zu haben, wenn die Sprache selbst automatisch damit umgehen könnte.
Ingenieur
Es gibt Hunderte anderer Beispiele wie dieses. Können Sie mir ein Beispiel für die Situation geben, über die Sie sprechen?
Scott C Wilson
-1

Mitglieder dürfen keine Schnittstellen verwenden, da diese Sprachen dann mit dem schrecklichen Übel, der Mehrfachvererbung, fertig werden müssten.

DeadMG
quelle
2
Ich bin mir nicht sicher, ob ich folge. Warum sollte das Zulassen von Mitgliedsvariablen in einer Schnittstelle die Unterstützung für Mehrfachvererbung erfordern oder implizieren?
Steve Mallam