2015-02-19 10 views
5

Also jetzt habe ich zwei Klassen der gleichen Klasse Typ, z.Kann ich von einer zur Laufzeit ausgewählten OCaml-Klasse erben?

class foo : foo_type = object ... end 

class bar : foo_type = object ... end 

Ich möchte eine dritte Klasse haben, die entweder von foo oder bar zur Laufzeit übernimmt. Z.B. (Pseudo-Syntax)

class baz (some_parent_class : foo_type) = object 
    inherit some_parent_class 
    ... 
end 

Ist das in OCaml möglich?

Anwendungsfall: Ich verwende Objekte zum Erstellen von AST-Besuchern, und ich möchte diese Besucher basierend auf einer Reihe von Laufzeitkriterien kombinieren können, so dass sie nur einen kombinierten Durchlauf über den AST ausführen.

Edit: Ich glaube, ich habe einen Weg gefunden, um die gewünschte Klasse mit First-Class-Module zu erstellen:

class type visitor_type = object end 

module type VMod = sig 
    class visitor : visitor_type 
end 

let mk_visitor m = 
    let module M = (val m : VMod) in 
    (module struct 
    class visitor = object 
     inherit M.visitor 
    end 
    end : VMod) 

Allerdings scheint es ein wenig Kreisverkehr eine Klasse in einem Modul zu haben, um zu wickeln mach es "erstklassig". Wenn es einen einfacheren Weg gibt, lass es mich wissen.

+0

Sie erleichtern diese ein wenig mit 'lassen mk_visitor (Modul M: VMod) = ... 'anstelle des' Let-Moduls'. – gsg

+0

Ja, ich werde das tun, wenn die Codebase an Upgrades auf OCaml 4 arbeitet. Momentan unterstützen wir noch 3.12. – int3

Antwort

3

Nicht im Gegensatz zu dem, was Jeffrey sagte, aber Sie können dies mit erstklassigen Modulen erreichen. Außerdem bin ich nicht sicher, ob Sie wirklich Klassen zur Laufzeit erstellen müssen, vielleicht wäre das Erstellen eines Objekts ausreichend. Wenn Sie ein anderes Verhalten haben wollen, dann reicht das.

+0

Sehen Sie meine Bearbeitung - Ich denke, ich habe herausgefunden, wie man es mit erstklassigen Modulen macht, obwohl es bedauerlich scheint, dass Klassen nicht selbst erstklassig sind. – int3

+0

Ja, Klassen in OCaml sind nicht sehr beliebt, deshalb sind sie nicht in beiden Sinne erstklassig. – ivg

2

OCaml hat ein statisches System. Sie können zur Laufzeit nichts tun, was den Typ von etwas beeinflussen würde. Vererbung wirkt sich auf die Arten von Dingen aus und kann daher nicht zur Laufzeit auftreten.

(Ihr Code verwechselt auch Typen mit Werten, was verständlich ist.)

Es ist wahrscheinlich eine Art und Weise zu nahe zu kommen, was Sie wollen, während die erwünschten Eigenschaften statischer Typisierung zu halten. Was du tatsächlich brauchst, mag vielleicht mehr wie Funktionszusammensetzung sein.

+0

Wenn ich von einer Klasse mit einem bekannten Klassentyp erben sollte, sollte der Typ der Kindklasse nicht zur Kompilierzeit ableitbar sein? – int3

+0

Die Vererbung erfolgt während der Kompilierung, sie ist Teil der Definition einer Klasse (eines Typs). Sie können natürlich einen Wert zur Laufzeit haben, der eine Instanz irgendeiner Unterklasse einer Klasse sein könnte. Dies ist nur eine normale OO-Semantik. Aber vielleicht verstehe ich nicht, was du verlangst. –

+0

Macht meine Bearbeitung es klarer? Mein Verständnis ist, dass Klassen und Klassenarten unterschiedlich sind, und letztere muss zur Kompilierungszeit festgelegt werden, aber nicht die erstere. – int3

4

Dies ist nur eine sauberere Umsetzung dessen, was man bereits vorgeschlagen, aber ich würde es tun, wie folgt:

module type Foo = sig 
    class c : object 
    method x : int 
    end 
end 

module A = struct 
    class c = object method x = 4 end 
end 

module B = struct 
    class c = object method x = 5 end 
end 

let condition = true 

module M = (val if condition then (module A) else (module B) : Foo) 

class d = object (self) 
    inherit M.c 
    method y = self#x + 2 
end 
Verwandte Themen