Latente Typisierung mit Interface und Enum

7

Ich habe eine IDevice Schnittstelle und zwei enum Realisierungen dieser Schnittstelle: AndroidDevice und IosDevice . Das Problem ist: Ich möchte latente Typisierung verwenden und values() method für eine Schnittstellenreferenz aufrufen:

%Vor%

Also muss ich public IDevice[] values(); zu meiner Schnittstelle hinzufügen:

%Vor%

Aber es funktioniert nicht. Eclipse fragt mich nach remove static modifiers from AndroidDevice(...)

Bitte:

  1. Erkläre mir, warum es nicht funktioniert?
  2. Was ist die beste Lösung für dieses Problem, sollte ich stattdessen Reflektion verwenden?
Rudziankoŭ 20.10.2015, 15:26
quelle

6 Antworten

4

Verwenden Sie einen Typ-Schnittpunkt:

%Vor%

Die an Enum<T> gebundene Eigenschaft stellt sicher, dass deviceClass.getEnumConstants() Werte zurückgibt, und die an & IDevice gebundene Angabe stellt sicher, dass Sie eine IDevice zurück erhalten.

Nennen Sie es wie folgt:

%Vor%     
Bohemian 23.10.2015, 09:54
quelle
7

Grund warum es nicht funktioniert ist, weil eine statische values() -Methode implizit für jede enum definiert ist.

%Vor%

Wenn Sie also eine statische Methode definiert haben, können Sie keine neue Methode auf Instanzebene mit derselben Signatur hinzufügen.

Der einfachste Weg, das Problem zu beheben, ist die Verwendung eines anderen Methodennamens.

%Vor%     
Mohit 23.10.2015 06:44
quelle
4
  1. Der Code funktioniert nicht, da Ihre Enumerationen, die die IDevice-Schnittstelle implementieren, zwei in Konflikt stehende Definitionen der Methode values() haben, sodass Ihr Code nicht kompiliert wird. Da Sie nach glaubwürdigen und offiziellen Referenzen gefragt haben, werde ich einen Drilldown durchführen. Beachten Sie, dass enums implizit eine Methode statisch values() erstellen (siehe JVM spec sec. 8.9.2 ). Ihre IDevice-Schnittstellenmethode verfügt jedoch auch über eine Methode Instanz namens values() . Beachten Sie, dass, wenn eine Klasse, die eine Schnittstelle implementiert, eine Basisklasse erweitert, diese neu definierte Methode in der Unterklasse bestehende Implementierungen überschreibt, die von der Basisklasse definiert wurden. Die Implementierung der IDevice-Instanz values ​​() -Methode überschreibt also die vorhandene statische Definition der values ​​() -Methode (siehe JVM spec sec. 8.4.8.1 ). Laut diesem Abschnitt ist es ein Kompilierzeitfehler für eine Instanzmethode, eine statische Methode zu überschreiben.
  2. Ich denke nicht, dass die Reflektion helfen wird, da dies ein Problem bei der Kompilierung ist. Stattdessen würde ich empfehlen, dass IDevice stattdessen eine Methode definiert, die values() ähnelt, also getValues() , wobei die Implementierung von getValues() nur values() aufruft. Siehe das folgende Code-Snippet. Der vollständige Code kann in der Demo auf IDEOne angezeigt werden:

    %Vor%
entpnerd 23.10.2015 07:36
quelle
4

Sie nähern sich dem vom falschen Ende her. Lassen Sie die Enum-Klassen stattdessen die Prüfungen behandeln:

Java 7

%Vor%

%Vor%

%Vor%

Dann:

%Vor%

Java 8

Wenn Sie auf Java 8 sind (Glücklicherweise!), können Sie das mit etwas zusätzlicher Magie tun:

%Vor%

%Vor%

%Vor%

Schließlich:

%Vor%     
Tomas 26.10.2015 20:28
quelle
2
  
  1. Erkläre mir, warum es nicht funktioniert?
  2.   

Wenn values() in Ihrer IDevice -Schnittstelle deklariert ist und dann ein Enum es implementiert, werden Sie erst nach der Kompilierung auf ein Problem stoßen.

Dies liegt daran, dass der Compiler eine static values() -Methode eingibt, die ein Array aller Werte in der Enumeration zurückgibt, daher wird es sich beschweren, den Modifizierer static zu entfernen.

Sie können die in values() definierte Instanzmethode IDevice nicht mit einer static -Methode derselben Signatur überschreiben, was der Compiler im Wesentlichen versucht.

  
  1. Was ist die beste Lösung für dieses Problem, sollte ich stattdessen Reflektion verwenden?
  2.   

Sie sollten Ihre IDevice -Schnittstelle vielleicht einfach als Tag ohne Methoden verwenden?

Weitere Informationen finden Sie unter:

Ссылка

    
kstandell 29.10.2015 15:54
quelle
1

Diese Frage kann nicht beantwortet werden, ohne zumindest die Methodendeklarationen in AndroidDevice zu sehen. Ich nehme an, dass die AndroidDevice#values() -Methode als static markiert ist, was nicht erlaubt ist, wenn man den Regeln der Vererbung in Java folgt (möglicherweise in keiner OO-Sprache). Der Grund dafür ist, dass "statisch" bedeutet, dass die Methode für die Klasse "lebt" und Sie keine Instanz für den Zugriff auf die Methode benötigen. In einer Schnittstelle deklarieren Sie so genannte Instanzmethoden. Sie benötigen also eine Instanz, um auf die Methode zuzugreifen. Sie müssen Instanzmethoden verwenden, wenn Sie mit Zuständen arbeiten müssen, die Sie in Ihrem Fall durch Zugriff auf die Instanzwerte ausführen möchten. Sie können nicht statisch (via Klasse) auf Instanzmethoden oder -zustände zugreifen, weil der Kontext nicht bekannt wäre.

Ohne den AndroidDevice-Code zu kennen, schlage ich vor, über die Art und Weise nachzudenken, wie Sie auf die Methode values() zugreifen möchten. IMHO der statische Zugriff ist nicht korrekt. Wenn Sie glauben, dass der statische Zugriff für Sie geeignet ist, sollten Sie sich die Methoden für statische Schnittstellen ansehen, die mit Java 8 eingeführt wurden.

Aber auch wenn Sie einen Zustand haben und auf diesen Zustand zugreifen wollen, ist der statische Zugriff nicht der richtige objektorientierte Weg.

    
Dirk Fauth 23.10.2015 06:47
quelle

Tags und Links