アクセス制御の抜け穴 (OCaml編)

Obj.magic 最強、で終わらそうと思ったのですがそう単純な話でもないらしい。
まず OCaml の private メソッドは、Javaなどのprotected相当で、継承した先のクラスからアクセスすることができます。
しかし呼び出せるのは自分に対してだけで、引数として受け取ったオブジェクトに対して呼び出すといったことはできません。method f x = x#g などと定義すると、fの引数xには"gというpublicメソッドを持った型"しかつけられなくなります。

class hoge = object
  method private priv = print_endline "hoge:private"
end
class fuga = object
  inherit hoge as super     (* hogeを継承 *)
  method priv = super#priv  (* 同名のメソッドをpublicに再定義可能 *)
  method call_priv (x:hoge) = x#priv  (* type error *)
end
    method call_priv (x:hoge) = x#priv
                                ^
This expression has type hoge
It has no method priv

また、private メソッドは、class type を制限することで継承先クラスにも見せない、本当にそのクラスだけのためのメソッドにすることができます (モジュールのシグネチャを制限するのと同じような感じ)。

class hoge : object
  (* priv はない *)
end = object
  method private priv = print_endline "hoge:private"
end
class fuga = object
  inherit hoge as super
  (* priv は使えない *)
  method func = super#priv; print_endline "fuga:func"
end
    method func = super#priv
                  ^^^^^
This expression has no method priv

で、メソッドがprivateかどうかってのは純粋に型の問題でコンパイラさえごまかしてしまえばなんとかなりそうだと思ったので Obj.magic でいじれば十分だろうと考えたのですが、うまくいったりいかなかったり。内部表現どうなってのコレ。

class type visible = object
  method priv : unit    (* public *)
end
class hoge = object
  method private priv = print_endline "hoge:private"
end

let _ =
  let x = new hoge in
  let y:visible = Obj.magic x in
  y#priv
hoge:private

これはうまくいく。

class type restricted = object
  (* empty *)
end
class type visible = object
  method hidden : unit
end
class hoge : restricted = object
  method private hidden = print_endline "hoge:hidden"
end

let _ =
  let x = new hoge in
  let y:visible = Obj.magic x in
  y#hidden
hoge:hidden

これもうまくいく。しかし

class type visible = object
  method priv1 : unit
  method priv2 : unit
end
class hoge = object
  method private priv1 = print_endline "hoge:private 1"
  method private priv2 = print_endline "hoge:private 2"
end

let _ =
  let x = new hoge in
  let y:visible = Obj.magic x in
  y#priv1;
  y#priv2
hoge:private 2
hoge:private 2

二つ以上になるとうまくいかない!?

うまくいかない場合について、もう少し厳密に調べたい。