Version française
Home     About     Download     Resources     Contact us    
Browse thread
Re: [Caml-list] Re: OO programming
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Julien Moutinho <julien.moutinho@g...>
Subject: Re: [Caml-list] Re: OO programming
On Thu, Feb 21, 2008 at 08:47:17PM +0100, Tiphaine.Turpin wrote:
> [...]

Below is a couple of design patterns which may be of interest to you.
The first one uses the [and] keyword with [class].
The second one uses the [and] keyword with [class type].

One advantage of the later being its capacity to be split
into several files (namely: header.ml, observer.ml and subject.ml),
but it is a little bit more verbose.

BTW, See also this chapter focusing on POO with OCaml:
  http://caml.inria.fr/pub/docs/oreilly-book/html/index.html#chap-POO

HTH.


# First design: implementation
# -----------------------------

% cat tiph_oo_and.ml
class ['msg] observer
  (subject: 'msg subject) =
  object
    method subject = subject
    method send : 'msg -> unit = fun _ -> ()
  end
and ['msg] subject =
  object (self)
    method private coerce =
        (self :> 'msg subject)
    val mutable observers : 'msg observer list = []
    method add () =
        let o = new observer self#coerce in
        observers <- o :: observers; o
    method notify (msg: 'msg) =
        List.iter
          (fun obs -> obs#send msg)
          observers
  end

let s = new subject
let o = s#add ()
let () = o#send `HELLO

# First design: interface
# -----------------------------

% ocamlc -i tiph_oo.ml
class ['a] observer :
  'a subject ->
  object
    method send : 'a -> unit
    method subject : 'a subject
  end

and ['a] subject :
  object
    val mutable observers : 'a observer list
    method add : unit -> 'a observer
    method private coerce : 'a subject
    method notify : 'a -> unit
  end

val s : _[> `HELLO ] subject
val o : _[> `HELLO ] observer

# Second design: implementation
# -----------------------------

% cat tiph_oo_mod.ml
module Header =
  struct
    class type ['msg] observer =
      object
        method subject : 'msg subject
        method send    : 'msg -> unit
      end
    and ['msg] subject =
      object
        method add    : unit -> 'msg observer
        method notify : 'msg -> unit
      end
  end

module Observer =
  struct
    class ['msg] observer :
      'msg Header.subject ->
      ['msg] Header.observer =
      fun subject ->
      object
        method subject = subject
        method send = fun _ -> ()
      end
  end

module Subject =
  struct
    class ['msg] subject :
      ['msg] Header.subject =
      object (self)
        method private coerce =
            (self :> 'msg subject)
        val mutable observers = []
        method add () =
            let o = (new Observer.observer self#coerce :> 'msg Header.observer) in
            observers <- o :: observers; o
        method notify (msg: 'msg) =
            List.iter
              (fun obs -> obs#send msg)
              observers
      end
  end

let s = new Subject.subject
let o = s#add ()
let () = o#send `HELLO

module Subject__alternative =
  (* NOTE: in this alternative, a double coercion is used
   * in order to have a [subject] class bigger than
   * [Header.subject] (a public method [some_method] here). *)
  struct
    class ['msg] subject =
      object (self)
        method private coerce =
            ((self :> 'msg subject) :> 'msg Header.subject)
        val mutable observers = []
        method add () =
            let o = (new Observer.observer self#coerce :> 'msg Header.observer) in
            observers <- o :: observers; o
        method notify (msg: 'msg) =
            List.iter
              (fun obs -> obs#send msg)
              observers
        method some_method = ()
      end
  end

let s_a = new Subject__alternative.subject
let o_a = s_a#add ()
let () = o_a#send `HI


# Second design: interface
# -----------------------------

% ocamlc -i tiph_oo_mod.ml
module Header :
  sig
    class type ['a] observer =
      object method send : 'a -> unit method subject : 'a subject end
    and ['a] subject =
      object method add : unit -> 'a observer method notify : 'a -> unit end
  end

module Observer :
  sig class ['a] observer : 'a Header.subject -> ['a] Header.observer end

module Subject : sig class ['a] subject : ['a] Header.subject end

val s : _[> `HELLO ] Subject.subject
val o : _[> `HELLO ] Header.observer


module Subject__alternative :
  sig
    class ['a] subject :
      object
        val mutable observers : 'a Header.observer list
        method add : unit -> 'a Header.observer
        method private coerce : 'a Header.subject
        method notify : 'a -> unit
        method some_method : unit
      end
  end

val s_a : _[> `HI ] Subject__alternative.subject
val o_a : _[> `HI ] Header.observer