From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: * X-Spam-Status: No, score=1.1 required=5.0 tests=AWL,SPF_NEUTRAL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by yquem.inria.fr (Postfix) with ESMTP id 24B9EBBC1 for ; Fri, 22 Feb 2008 00:54:26 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgAAACSevUfRVYa+mWdsb2JhbACQXwEBAQEBBgQECwgYmRKHFw X-IronPort-AV: E=Sophos;i="4.25,388,1199660400"; d="scan'208";a="22893717" Received: from mu-out-0910.google.com ([209.85.134.190]) by mail4-smtp-sop.national.inria.fr with ESMTP; 22 Feb 2008 00:54:22 +0100 Received: by mu-out-0910.google.com with SMTP id w8so306830mue.4 for ; Thu, 21 Feb 2008 15:54:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:received:date:to:subject:message-id:mail-followup-to:references:mime-version:content-type:content-disposition:in-reply-to:user-agent:from; bh=4sLtXP5ww5NAtUdIroOy4Jvrn3lzl74aDscx88Li3As=; b=u2J13VL+FNrK9Zjb3kTMMvMVYSEDTb9imw06g+cviXPf6GLVrDXjFKOpw7zhmdJlnZUm4hbHOaBoYx8bOII89inY+dHq4ZhAq56Np2e8LV3KhiMm6+91JJot8fFexfv0y75jzXtNRXG024a+fpZ4fNMYPfX0gYyopNdJgwte7eQ= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:to:subject:message-id:mail-followup-to:references:mime-version:content-type:content-disposition:in-reply-to:user-agent:from; b=XHhjoWxC6iRlcugdgWZ3PW/HmAFoI12a6JVnoXnw0RMB2Y/+9/DMnFdDusBswnVEy8MdRm82q/lJLclMUy0CFjI8cP0iHEAB2fR4zmoowpBW88lT5+5BDTf37k6b8T4jFnjEzG5ibCg7K+RdhqUz+476iJIvzP1iv+/7mM6Mc+4= Received: by 10.86.89.4 with SMTP id m4mr4031921fgb.45.1203638061824; Thu, 21 Feb 2008 15:54:21 -0800 (PST) Received: from persocom ( [83.201.57.65]) by mx.google.com with ESMTPS id d4sm671621fga.2.2008.02.21.15.54.14 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 21 Feb 2008 15:54:19 -0800 (PST) Received: by persocom (sSMTP sendmail emulation); Fri, 22 Feb 2008 00:56:46 +0100 Date: Fri, 22 Feb 2008 00:56:46 +0100 To: caml-list@yquem.inria.fr Subject: Re: [Caml-list] Re: OO programming Message-ID: <20080221235646.GA14422@localhost> Mail-Followup-To: Julien Moutinho , caml-list@yquem.inria.fr References: <47BDADE9.4030902@free.fr> <47BDD545.7020404@free.fr> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <47BDD545.7020404@free.fr> User-Agent: Mutt/1.5.17+20080114 (2008-01-14) From: Julien Moutinho X-Spam: no; 0.00; 0100,:01 verbose:01 ocaml:01 oreilly-book:01 val:01 mutable:01 observers:01 observers:01 iter:01 ocamlc:01 val:01 mutable:01 struct:01 struct:01 iter:01 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