Simulieren von ADTs in Java

8

Eine Anwendung kann in zwei Modi arbeiten - "Echtzeit", in der jede Aktualisierung des Zustandes der Welt betrachtet wird, oder "abgetastet", wobei nur alle Millisekunden der Zustand der Welt betrachtet wird.

Wenn ich Haskell (oder eine andere Sprache mit ADTs) schreiben würde, würde ich dies als

modellieren %Vor%

das wie folgt typsicher verwendet werden kann

%Vor%

Ich sage, dass es "typsicher" ist, denn wenn Sie im Echtzeitmodus laufen, können Sie nicht auf das Feld interval zugreifen (das genau dann zur Verfügung steht, wenn Sie es benötigen) im abgetasteten Modus).

Wie kann ich dasselbe in Java typsicher modellieren? Das heißt, ich möchte

  • Um eine Klasse (oder enum) zu definieren, die zwischen den beiden Modi unterscheidet, und
  • Den Zugriff auf das Feld interval im Echtzeitmodus und
  • zu verbieten
  • Um all dies vom Compiler überprüfen zu lassen.

Ist das in Java möglich? Wenn nicht, was ist der idiomatische Weg, um diese Art von Sicherheit zu erreichen?

    
Chris Taylor 15.07.2015, 11:14
quelle

3 Antworten

9

Die traditionelle Art, geschlossene algebraische Datentypen in einer Sprache wie Java zu emulieren, die nur offene Klassen (die jederzeit vererbt werden können) typsicher bereitstellt, ist die Besuchermuster :

%Vor%

Wie @ user3237465 bemerkt, sind mehrere Kodierungen von Datentypen möglich, die zufällig zusammenfallen, wenn der Datentyp nicht rekursiv ist: Die Church-Kodierung ist eine Falte: Sie können einen Wert akkumulieren durch Rekursion über den Church-encoded Datentyp. Die Scott-Codierung entspricht dem tatsächlichen Mustervergleich. In jedem Fall können Besucher verwendet werden, um alle diese Kodierungen zu implementieren. Danke für den Anstupser, @ user3237465!

    
pyon 15.07.2015, 11:51
quelle
2

Sie können eine Schnittstelle Mode

deklarieren %Vor%

Und dann können Sie zwei Klassen haben, die diese Schnittstelle implementieren

%Vor%

Dann deklarieren Sie eine Variable vom Typ Mode

%Vor%

Und da mode vom Typ Mode ist, können Sie nur auf das zugreifen, was in der Schnittstelle deklariert ist. Sie können also einfach mode.doSmth() aufrufen, und je nachdem, wie Sie mode initialisiert haben, wird es in Echtzeit oder als Stichprobe ausgeführt.

Wenn die Klassen etwas Code teilen, dann können Sie eine Klasse abstract anstelle von interface deklarieren und beide Klassen extend diese Klasse haben. Dann können sie die allgemeinen Methoden aufrufen, die in der Klasse abstract deklariert sind (die mit protected visibility deklariert werden sollte, damit nur Unterklassen sie sehen können)

    
xp500 15.07.2015 11:23
quelle
0

Ja, natürlich ist es möglich, obwohl es von der Komplexität abhängt, die Sie bereit sind zu erreichen.

Wenn Sie die höchste Stufe der Typensicherheit erreichen wollen, empfehle ich Ihnen, eine Abstraktion (genannt AbstractModeManager ) zu deklarieren, deren Aufgabe es sein wird, den Zustand der Welt abzufragen und zu speichern in Instanzvariablen, auf die durch öffentliche Getter-Methoden zugegriffen werden kann. Und es muss auch wissen, wann es ein Update gab:

%Vor%

Darunter müssen Sie zwei Implementierungen programmieren: Eine für die Echtzeit und eine weitere für die Stichprobe:

%Vor%

Und zuletzt müssen Sie entscheiden, welche davon in jedem Fall verwendet werden soll. Speichern Sie sie in einer Variablen:

%Vor%

... Und rufe systematisch bei jedem Update im System auf:

%Vor%

Auf diese Weise ist es nach dem Initialisieren dieser Variablen nicht wichtig, welchen Modus das System ausführt: Dieses Verhalten wird Ihrer -Abstraktion überlassen.

    
Little Santi 15.07.2015 11:39
quelle