OCAML オブジェクトのこの動作の理由を理解したいと思います。A
別のクラスのオブジェクトのメソッドを呼び出すクラスがあるとしますB
。概略的には、A#f は B#g と B#h を呼び出します。OOP では通常、B を固定具象クラスとして使用することは避け、代わりに B のインターフェイスのみを宣言します。OCAML でこれを行う最善の方法は何ですか? いくつかのオプションを試しましたが、機能するものと機能しないものがある理由がよくわかりません。コードサンプルを次に示します。
バージョン 1:
# class classA = object
method f b = b#g + b#h
end ;;
Error: Some type variables are unbound in this type:
class a : object method f : < g : int; h : int; .. > -> int end
The method f has type (< g : int; h : int; .. > as 'a) -> int where 'a
is unbound
この動作はよく知られています。OCAML は がb
open オブジェクト型を持っていると正しく推測します<g:int;h:int;..>
が、クラスが型変数を宣言していないと不平を言います。したがって、型変数classA
が必要なようです。次に、型変数を明示的に導入しました。
バージョン 2:
# class ['a] classA2 = object
method f (b:'a) = b#g + b#h
end ;;
class ['a] classA2 :
object constraint 'a = < g : int; h : int; .. > method f : 'a -> int end
これは機能しますが、OCAML が示すように、クラスは型制約を使用して明示的にポリモーフィックになりました。クラス型に型変数が含まれていることも紛らわしいですが、の型値を指定しなく'a
ても言えます。なぜそれが可能なのですか?let x = new classA2
'a
のもう 1 つの欠点classA2
は、明示的な型制約(b:'a)
に型変数が含まれていることです。結局のところ、b
未知の型ではなく、固定されたインターフェイスに準拠する必要があることはわかっています'a
。このインターフェースが本当に正しいことを OCAML に検証してもらいたいのです。
バージョン 3 では、最初にインターフェイスclassB
をクラス型として宣言し、次にb
この型でなければならないと宣言しました。
# class type classB = object method g:int method h:int end;;
class type classB = object method g : int method h : int end
# class classA3 = object method f (b:classB) = b#g + b#h end;;
class classA3 : object method f : classB -> int end
classA3
これも機能しますが、私の戸惑いは残ります。明示的なポリモーフィズムが必要なくなったのはなぜですか?
質問の要約:
- が型変数で宣言されているのに
new classA2
型を指定せずに使えるのはなぜですか?'a
classA2
'a
classA3
が型制約を受け入れ、(b:classB)
バインドされた型変数を必要としないのはなぜですか?- と の機能には微妙な違いが
classA2
ありclassA3
ますか? もしそうなら、どのように違いますか?