2016-03-12 6 views
1

Pour mes liaisons Qt5, j'ai un arbre d'héritage de classes ocaml qui prend un objet C++ en paramètre. Donc ceci fonctionne le long de la chaine d'héritage la classe de base a un method obj retournant un 'a t où' a est le type self. Le problème est maintenant que les utilisateurs doivent être en mesure d'hériter de mes classes ocaml, donc je dois fermer le type ou sinon supprimer ou masquer le method obj et le paramètre obj. L'utilisateur n'a aucun moyen de créer un objet C++ dérivé.fermeture d'un type d'objet dans ocaml

type 'a t (* type of the c++ objects *) 

(* ocaml wrapper around the c++ object *) 
class foo (obj : 'a t) = object(self:'a) 
    method obj = obj 
    method foo = "foo" 
end 

(* external function returning c++ object *) 
let make_foo_t() = ((Obj.magic 0) : foo t) 

(* way for the user to create a foo *) 
let make() = new foo (make_foo_t()) 

(* class the user can derive from hiding the c++ object *) 
class bar = object 
    inherit foo (make_foo_t()) 
    method bar = "bar" 
end 

(* user *) 
let x = new bar;; 

class derived_bar = object 
    inherit bar 
    method dervived_bar = "derived_bar" 
end 

Le problème est que je n'arrive pas à faire fonctionner la barre de classe. Tout ce que je fais, ocaml se plaint que "le type d'individu ne peut pas être unifié avec un type d'objet fermé" ou "le type d'individu ne peut pas échapper à sa classe".

Des idées?

Répondre

1

Après beaucoup d'essais et plusieurs démarrages à partir de zéro, j'ai trouvé une solution qui fonctionne même si elle n'est pas jolie. Toujours à la recherche quelque chose de mieux:

module type Make = sig 
    val stub : unit -> #foo t 
end 

class bar() = 
    let obj = 
    let module E = (val (module struct 
     external stub : unit -> #foo t = "stub" 
    end) : Make) 
    in 
    E.stub text 
    in 
object 
    inherit foo obj 
end 

Je déclare « stub » en fonction externe retour « t où » une sous-classe est aussi directe ou indirecte de foo. J'utilise un module local de première classe pour limiter l'exposition de ce bout à l'intérieur de la barre de classe afin qu'il ne puisse pas être mal utilisé même si aucun fichier .mli n'est présent.

Remarque: la barre de classe doit prendre un argument (ici unité) ou ne pas taper. Ça m'a pris un moment pour comprendre ça.

+0

Pourquoi la barre nécessite-t-elle un argot fictif? –