• 日時 :2006/8/7 (Mon)
  • 場所 :名大 理学部1号館(多元数理科学研究科) 307室
  • 時刻 :18:00〜19:30
  • 参加者:9名
  • OCaml オブジェクトシステムについて by 小笠原さん
  • とりあえず、貼り付け :) -- 小笠原? 2006-08-09 (水) 10:23:48
  • きれいにしました。 -- けいご? 2006-08-09 (水) 13:59:49

オブジェクト指向機能 †

クラスとオブジェクト †

クラスはキーワード class の後にクラス名を付けて宣言する。

# class counter = 
   object
     val mutable i = 0
     method get = i    
     method inc = i <- i + 1
     method dec = i <- i - 1
   end;;
class counter :
 object
   val mutable i : int
   method dec : unit
   method get : int
   method inc : unit
 end
#   

モジュールと同様に複数の式を一つのまとまりとして扱うことが出来る。ただし、モジュールと違い、複数の値全体がひとつの値として扱われている。 また、val と method の区別がある。val はインスタンス毎に生成される値 (Counter.t 型の値に対応する)、method はインスタンスに共通の値(Counter モジュールに属する値に対応する)である。

counter クラスから counter オブジェクトをインスタンス化して使用するには、new キーワードを用いる。また、オブジェクトに # とメソッド名を付けて、メソッドを起動出来る。

# let c =
   new counter
 in
 c#inc;
 c#inc;
 c#get;;
- : int = 2
# 

クラスを定義せずに直接オブジェクトを作ることも可能。

# let c = object val mutable i = 0 method get = i method inc = i <- i + 100 end;;
val c : < get : int; inc : unit > = <obj>
# c#inc; 
 c#inc; 
 c#get;;
- : int = 200
# 

オブジェクトは値であり、関数の引数として利用できることが重要な点である。

色々な特徴 &dagger;

クラスを継承したい場合、inhreit キーワードを用いる。

# class setable init =
  let restrict x =
    max 0 (min 100 x)
  in
  object (self)
    inherit counter
    method private set x = i <- x
    initializer self#set (restrict init)
  end;;
class setable :
 int ->
 object
   val mutable i : int
   method dec : unit
   method get : int
   method inc : unit
   method private set : int -> unit
 end
# let s = new setable 200 in s#get;;
- : int = 100
# 

上の例では inherit の他にクラス定義に便利な機能を(無理矢理)利用してみた。以下の特徴がある。

  • setable を int -> オブジェクト型 という関数にしている
  • 関数内で restrict 関数を定義している
  • オブジェクト自身に self という名前を付けている
  • private キーワード指定により、set メソッドを隠蔽している
  • initializer キーワードにより、初期化処理を行っている

as キーワードにより、親クラスに名前を付けることも出来る。

# class resetable init =
  object
    inherit setable init as super
    method reset = super#set 0
  end;;
class resetable :
 int ->
 object
   val mutable i : int
   method dec : unit
   method get : int
   method inc : unit
   method reset : unit
   method private set : int -> unit
 end
#

private 指定されたメソッドもサブクラスで利用できることに注意。多重継承も可能である。もし同名のメソッドがある場合は、最後の定義のみが有効になる。

型変数付きメソッド &dagger;

クラスにおける parametric polymorphism の扱いには少し注意が必要である。クラスメソッドの型変数は、クラスもしくはメソッドに束縛されていなければならない。

# class id = object method id x = x end;;
Some type variables are unbound in this type:
 class id : object method id : 'a -> 'a end
The method id has type 'a -> 'a where 'a is unbound
# 
  • クラスに束縛する場合
    # class ['a] id = object method id (x : 'a) = x end;;
    class ['a] id : object method id : 'a -> 'a end
    # let s = new id;;
    val s : '_a id = <obj>
    # s#id "str";;
    - : string = "str"
    # s#id 1;;
    This expression has type int but is here used with type string
    # 
  • メソッドに束縛する場合
    # class id = object method id : 'a. 'a -> 'a = fun x -> x end;;
    class id : object method id : 'a -> 'a end
    # let i = new id;;
    val i : id = <obj>
    # i#id "str";;
    - : string = "str"
    # i#id 1;;
    - : int = 1
    # 

virtual メソッド &dagger;

クラスが継承される事を前提にして、型だけ定義して実装を伴わないメソッドを宣言できる。

# class virtual printable =
  object (self)
    inherit counter as super
    method virtual print : unit
    method inc =
      self#print;
      super#inc
  end;;
class virtual printable :
 object
   val mutable i : int
   method dec : unit
   method get : int
   method inc : unit
   method virtual print : unit
 end
# new printable;;
One cannot create instances of the virtual class printable
#

printable クラスを継承して print メソッドを実装してみる。

# class cui_printable =
   object
   inherit printable
   method print =
     Format.printf "%d@," i
 end;;        
class cui_printable :
 object
   val mutable i : int
   method dec : unit
   method get : int
   method inc : unit
   method print : unit
 end
# let cp = new cui_printable;;
val cp : cui_printable = <obj>
# cp#inc;;
0
- : unit = ()
# cp#inc;;
1
- : unit = ()
# 
  • ファンクショナルなオブジェクト
  • バイナリメソッド
  • 相互再帰クラス
  • 型理論からの視点
    • subtype
    • existential types
    • bounded quantification
    • ADT との比較
      # let name x = x#name;;
      val name : < name : 'a; .. > -> 'a = <fun>
      #

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2008-02-21 (木) 15:31:16 (5902d)