Ich möchte wissen, ob es für die Implementiererklasse eine Möglichkeit gibt, die Objekthandles / Grundelemente wie bei Methoden zu deklarieren. für zB:
public interface Rectangle {
int height = 0;
int width = 0;
public int getHeight();
public int getWidth();
public void setHeight(int height);
public void setWidth(int width);
}
public class Tile implements Rectangle{
@Override
public int getHeight() {
return 0;
}
@Override
public int getWidth() {
return 0;
}
@Override
public void setHeight(int height) {
}
@Override
public void setWidth(int width) {
}
}
Wie können wir in der obigen Methode die Tile-Klasse dazu zwingen, Höhen- und Breitenattribute über die Schnittstelle zu deklarieren? Aus irgendeinem Grund möchte ich es nur mit Schnittstelle machen!
Ich dachte anfangs daran, es mit Vererbung zu verwenden. Aber was ist, ich muss mich mit 3 Klassen auseinandersetzen.!
- Rechteck
- Fliese
- JLabel.!
class Tile extends JLabel implements Rectangle {}
würde funktionieren.!
aber
class Tile extends JLabel extends Rectangle {}
würde nicht.!
final static
Modifikator an / wendet ihn an .Antworten:
Der Sinn einer Schnittstelle besteht darin, die öffentliche API anzugeben. Eine Schnittstelle hat keinen Status. Alle Variablen, die Sie erstellen, sind wirklich Konstanten (seien Sie also vorsichtig, wenn Sie veränderbare Objekte in Schnittstellen erstellen).
Grundsätzlich sagt eine Schnittstelle, dass hier alle Methoden aufgeführt sind, die eine Klasse, die sie implementiert, unterstützen muss. Es wäre wahrscheinlich besser gewesen, wenn die Entwickler von Java Konstanten in Schnittstellen nicht zugelassen hätten, aber zu spät, um dies jetzt zu beseitigen (und es gibt einige Fälle, in denen Konstanten in Schnittstellen sinnvoll sind).
Da Sie nur angeben, welche Methoden implementiert werden müssen, gibt es keine Vorstellung vom Status (keine Instanzvariablen). Wenn Sie möchten, dass jede Klasse eine bestimmte Variable hat, müssen Sie eine abstrakte Klasse verwenden.
Schließlich sollten Sie im Allgemeinen keine öffentlichen Variablen verwenden, daher ist die Idee, Variablen in eine Schnittstelle einzufügen, zunächst eine schlechte Idee.
Kurze Antwort - Sie können nicht tun, was Sie wollen, weil es in Java "falsch" ist.
Bearbeiten:
class Tile implements Rectangle { private int height; private int width; @Override public int getHeight() { return height; } @Override public int getWidth() { return width; } @Override public void setHeight(int h) { height = h; } @Override public void setWidth(int w) { width = w; } }
Eine alternative Version wäre:
abstract class AbstractRectangle implements Rectangle { private int height; private int width; @Override public int getHeight() { return height; } @Override public int getWidth() { return width; } @Override public void setHeight(int h) { height = h; } @Override public void setWidth(int w) { width = w; } } class Tile extends AbstractRectangle { }
quelle
getHeight
abstrakt deklarieren und überhaupt keine Höhe deklarieren, aber dann müssen Sie den Rückkehrcode jedes Mal wiederholen, damit Sie die Variable privat halten können.obj.Property
kann niemals einen anderen Code aufrufen , kann aberobj.Property()
& die beiden werden auf der Schnittstellenebene unterschiedlich behandelt.Für Schnittstellen müssen keine Instanzvariablen definiert werden - nur Methoden.
( Variablen können in Schnittstellen definiert werden , verhalten sich jedoch nicht wie erwartet: Sie werden wie folgt behandelt
final static
.)Viel Spaß beim Codieren.
quelle
In Java 8 wurden Standardmethoden für Schnittstellen eingeführt, mit denen Sie die Methoden verwenden können. Laut OOPs sollten Schnittstellen als Vertrag zwischen zwei Systemen / Parteien fungieren.
Trotzdem habe ich einen Weg gefunden, um Eigenschaften in der Benutzeroberfläche zu speichern. Ich gebe zu, es ist eine hässliche Implementierung.
import java.util.Map; import java.util.WeakHashMap; interface Rectangle { class Storage { private static final Map<Rectangle, Integer> heightMap = new WeakHashMap<>(); private static final Map<Rectangle, Integer> widthMap = new WeakHashMap<>(); } default public int getHeight() { return Storage.heightMap.get(this); } default public int getWidth() { return Storage.widthMap.get(this); } default public void setHeight(int height) { Storage.heightMap.put(this, height); } default public void setWidth(int width) { Storage.widthMap.put(this, width); } }
Diese Schnittstelle ist hässlich. Zum Speichern einfacher Eigenschaften wurden zwei Hashmaps benötigt, und jede Hashmap erstellt standardmäßig 16 Einträge. Wenn ein reales Objekt dereferenziert wird, muss JVM diese schwache Referenz zusätzlich entfernen.
quelle
Sie können dies nur mit einer abstrakten Klasse tun, nicht mit einer Schnittstelle.
Deklarieren Sie
Rectangle
alsabstract class
anstelle voninterface
und deklarieren Sie die Methoden, die von der Unterklasse implementiert werden müssen, alspublic abstract
. Dann erweitert classTile
die KlasseRectangle
und muss die abstrakten Methoden von implementierenRectangle
.quelle
In Java können Sie nicht. Schnittstelle hat mit Methoden und Signatur zu tun, es hat nicht mit dem internen Zustand eines Objekts zu tun - das ist eine Implementierungsfrage. Und das macht auch Sinn - ich meine, nur weil bestimmte Attribute existieren, heißt das nicht, dass sie von der implementierenden Klasse verwendet werden müssen. getHeight könnte tatsächlich auf die width-Variable verweisen (vorausgesetzt, der Implementierer ist ein Sadist).
(Hinweis: Dies gilt nicht für alle Sprachen. ActionScript ermöglicht die Deklaration von Pseudoattributen, und ich glaube, dass C # dies auch tut.)
quelle
Felder in Schnittstellen sind implizit
public static final
. (Auch Methoden sind implizit öffentlich, sodass Sie daspublic
Schlüsselwort löschen können.) Selbst wenn Sie eine abstrakte Klasse anstelle einer Schnittstelle verwenden, empfehle ich dringend, alle nicht konstant zu machen (public static final
einer primitiven oder unveränderlichen Objektreferenz)private
. Im Allgemeinen "Komposition der Vererbung vorziehen" - einTile
is-not-aRectangle
(natürlich können Sie Wortspiele mit "is-a" und "has-a" spielen).quelle
Tom hat etwas Wichtiges gesagt:
Wenn Sie anstelle von Erweiterungen und Implementierungen zwei Attribute definieren, eines vom Typ Rechteck, eines vom Typ Typ
JLabel
in IhrerTile
Klasse, können Sie aRectangle
entweder als Schnittstelle oder als Klasse definieren.Darüber hinaus würde ich normalerweise die Verwendung von Schnittstellen in Verbindung mit has-a fördern, aber ich denke, es wäre ein Overkill in Ihrer Situation. Sie sind jedoch der einzige, der über diesen Punkt entscheiden kann (Kompromissflexibilität / Überentwicklung).
quelle