インスタンス変数への代入を使わない point
クラスを定義することもできます。 {< ... >}
構文は「自分自身」(すなわち現在のオブジェクト)の、一部のインスタンス変数の値を変更したコピーを返します。
#
class functional_point y = object val x = y method get_x = x method move d = {< x = x + d >} end;;
class functional_point : int -> object ('a) val x : int method get_x : int method move : int -> 'a end
#
let p = new functional_point 7;;
val p : functional_point = <obj>
#
p#get_x;;
- : int = 7
#
(p#move 3)#get_x;;
- : int = 10
#
p#get_x;;
- : int = 7
型略記 functional_point
が再帰的であることに注意して下さい。このことは functional_point
のクラス型からも見て取れます。自身の型を 'a
とし 'a
が move
メソッドの型に現れています。
上の functional_point
の定義は次と同値ではありません。
#
class bad_functional_point y = object val x = y method get_x = x method move d = new bad_functional_point (x+d) end;;
class bad_functional_point : int -> object val x : int method get_x : int method move : int -> bad_functional_point end
どちらのクラスに属するオブジェクトも同じ振舞をしますが、子クラスのオブジェクトは違った振舞をします。後者の子クラスでは、 move
メソッドは親クラスのオブジェクトを返します。反対に、前者の子クラスでは、move
メソッドは子クラスのオブジェクトを返します。
ここで紹介した関数型更新は、 5.2.1 節「文字列 」で紹介するようにバイナリメソッドと組み合わせてよく用いられます。