From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by yquem.inria.fr (Postfix) with ESMTP id A21A3BB83 for ; Fri, 5 May 2006 12:47:15 +0200 (CEST) Received: from pauillac.inria.fr (pauillac.inria.fr [128.93.11.35]) by concorde.inria.fr (8.13.0/8.13.0) with ESMTP id k45AlETJ009732 for ; Fri, 5 May 2006 12:47:15 +0200 Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id MAA26393 for ; Fri, 5 May 2006 12:47:14 +0200 (MET DST) Received: from moutng.kundenserver.de (moutng.kundenserver.de [212.227.126.188]) by nez-perce.inria.fr (8.13.0/8.13.0) with ESMTP id k45AlADJ020696 for ; Fri, 5 May 2006 12:47:14 +0200 Received: from [84.58.130.74] (helo=gate.lan.gerd-stolpmann.de) by mrelayeu.kundenserver.de (node=mrelayeu8) with ESMTP (Nemesis), id 0ML2ov-1Fbxpw3lNJ-0007w5; Fri, 05 May 2006 12:47:05 +0200 Received: from flakew.lan.gerd-stolpmann.de (flakew.lan.gerd-stolpmann.de [192.168.0.32]) by gate.lan.gerd-stolpmann.de (Postfix) with ESMTP id B711FC07E; Fri, 5 May 2006 12:47:00 +0200 (CEST) Subject: Re: [Caml-list] OO design From: Gerd Stolpmann To: david.baelde@ens-lyon.org Cc: Ocaml In-Reply-To: <53c655920605050235k64e70333je8df813239ea3c53@mail.gmail.com> References: <53c655920605050235k64e70333je8df813239ea3c53@mail.gmail.com> Content-Type: text/plain Date: Fri, 05 May 2006 12:47:00 +0200 Message-Id: <1146826020.28638.124.camel@localhost.localdomain> Mime-Version: 1.0 X-Mailer: Evolution 2.4.1 Content-Transfer-Encoding: 7bit X-Provags-ID: kundenserver.de abuse@kundenserver.de login:a6865a839c0178d9aa0ce41878507ea2 X-Miltered: at concorde with ID 445B2D32.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Miltered: at nez-perce with ID 445B2D2E.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Spam: no; 0.00; gerd:01 stolpmann:01 overriding:01 ocaml:01 subclassing:01 o'caml:01 subclassing:01 foo:01 foo:01 functors:01 o'caml:01 sig:01 val:01 struct:01 gerd:01 X-Spam-Checker-Version: SpamAssassin 3.0.3 (2005-04-27) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=disabled version=3.0.3 Am Freitag, den 05.05.2006, 11:35 +0200 schrieb David Baelde: > Hi, > > I'm no OO guru, so my question may be irrelevant, or there just might > not be an answer, which wouldn't hurt.. > > Let's say that I have a base class, with some kind of activation > procedure: anybody wanting to use the class must call #enter before, > and then call #leave for releasing. Internally, the methods #do_enter > and #do_leave are called respectively at the first #enter and last > #leave. > > Nobody should call the #do_* directly, and I'd also like to make sure > the #enter and #leave are never overriden, since their behaviour is > important and actually much more complex than what I said. > > I could just rely on the user who derives my base class, but let's see > what we can do. First the #do_* should be made private, so they can be > defined in the derived classes, but never called from the outside. To > avoid the overriding of #enter and #leave the only solution seems to > make them normal functions instead of methods. But then how could > #enter call #do_enter ? I tried to first define the class with public > #enter and make that method private in the interface, but OCaml told > me that was impossible. > > I'm just curious if anybody has an opinion/idea about that. There is an easy solution if you completely forbid subclassing (see below). However, there is no water-proof solution, because class types are structural in O'Caml, i.e. you cannot prevent that a user simulates subclassing using this style: class pirate_foo (foo : official_foo) = object method enter = ... method leave = ... method other_method = foo # other_method end If you want to safely encapsulate a certain invariant into a structure you must go with modules/functors in O'Caml. To forbid explicit subclassing just do not to export the class as such: module Foo : sig class type foo_type = object method enter : ... method leave : ... ... end val create_foo : ... -> foo_type end = struct class type foo_type = object method enter : ... method leave : ... ... end class foo ... : foo_type = object method enter ... = ... method leave ... = ... ... end let create_foo ... = new foo ... end Without class, the user can no longer inherit from it. The created object, however, is fully usable. I do not see a way how to completely hide enter and leave from the class type. Gerd -- ------------------------------------------------------------ Gerd Stolpmann * Viktoriastr. 45 * 64293 Darmstadt * Germany gerd@gerd-stolpmann.de http://www.gerd-stolpmann.de Phone: +49-6151-153855 Fax: +49-6151-997714 ------------------------------------------------------------