2009-03-11 18 views
4

Ich lerne über OCaml OOP Konstrukte und implementiert dies teilweise heute, bis ich erkannte, ich habe keine Ahnung, wie eine polymorphe Match-Anweisung ohne das Schlüsselwort außerhalb des Objekts zu repräsentieren.Typ von on-the-fly in OCaml OOP-Konstrukt

class bar (param:string) = 
object (code) 

end;; 

class foo param = 
object (code) 
initializer 
    match param with 
    string -> Printf.printf "param is a string" 
    | bar -> Printf.printf "param is a bar"  
end;; 

let b = new bar "a string";; 
let f1 = new foo "test";; 
let f2 = new foo b;; 

Ist es möglich, den Typ des Objekts zu bestimmen, das on-the-fly übergeben wird?

Antwort

3

Diese Übereinstimmung tut nichts anderes als die Bindung 'param' zu 'string', ocaml sollte sagen, dass die zweite Übereinstimmung nicht verwendet wird. Ich glaube, dass Sie Variantentypen verwenden müssen, um den Abgleich durchzuführen. Im Folgenden finden Sie ein Beispiel mit polymorphen Variantentypen.

class bar (param:string) = 
    object (code) 
end 

class foo param = 
    object (code) 
    initializer 
    match param with 
    | `String str -> Printf.printf "param is a string" 
    | `Bar bar -> Printf.printf "param is a bar"  
end 

let b = new bar "a string" 
let f1 = new foo (`String "test") 
let f2 = new foo (`Bar b) 
2

Im Allgemeinen unterstützt OCaml keine Laufzeit-Identifizierung von Typen.

Das besagt, dass in der Laufzeitdarstellung eine kleine Typinformation eingebettet ist, damit der Garbage Collector funktionieren kann. Um festzustellen, ob etwas ein String ist, können Sie tun:

if Obj.tag (Obj.repr param) = Obj.string_tag then 

Mehr Informationen über OCaml der Laufzeitdarstellung in Interfacing C with Objective Caml zur Verfügung stehen. Diese Arten von Prüfungen laufen jedoch im Allgemeinen den Programmierarten zuwider, die OCaml fördert, und es ist nicht klar, wie Sie mit dieser speziellen Prüfung etwas Nützliches tun würden (Sie müssen in eine Zeichenkette konvertieren und den Typ verwüsten Sicherheit). Eine weitaus bessere Lösung besteht darin, einen algebraischen Datentyp oder polymorphe Varianten zu verwenden, um die gültigen Parametertypen und die Musterübereinstimmung darüber zu beschreiben.

Typsichere Downcasts könnten nützlich sein, werden aber von OCaml nicht unterstützt. Sie müssen Ihren eigenen Mechanismus rollen (oder, besser, um ihn herum entwerfen), wenn das was Sie suchen.

0

Die Idee einer polymorphen Match-Anweisung widerspricht der Idee der objektorientierten Programmierung! Anpassung des Verhaltens sollte in Objekten eingekapselt werden, dafür sind sie da. Code, der eine Klasse fragt, "was bist du eigentlich", signalisiert ein Designproblem.

Das heißt, wenn Sie Klassen, die Sie wirklich in der Lage sein zu sagen, was sie wirklich sind, ein Verfahren hierfür ist die einfachste Möglichkeit, nur hinzuzufügen, ist:

type typ = A | B 

class bar = 
object 
    method typ = A 
end 

class rebar = 
object 
    method typ = B 
end 

class foo param = 
object 
    initializer 
    match param#typ with 
    | A -> print_endline "This is a A" 
    | B -> print_endline "This is a B" 
end 

nicht polymorphe Varianten verwenden für Dies, da Sie den Vorteil der erschöpfenden Musteranpassung in Wartungsoperationen nicht nutzen können.

Noch einmal, wenn Sie dies tun, ignorieren Sie wahrscheinlich die Liskov substitution principle und bereiten arbeitsreiche Tage für den Wartungsbeauftragten Ihres Codes vor. Unsere Welt braucht diese Grausamkeit nicht!