From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (from majordomo@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id CAA02468; Sat, 14 Aug 2004 02:03:58 +0200 (MET DST) X-Authentication-Warning: pauillac.inria.fr: majordomo set sender to owner-caml-list@pauillac.inria.fr using -f 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 CAA02252 for ; Sat, 14 Aug 2004 02:03:57 +0200 (MET DST) Received: from mta10-svc.ntlworld.com (mta10-svc.ntlworld.com [62.253.162.94]) by nez-perce.inria.fr (8.12.10/8.12.10) with ESMTP id i7E03umL013269 for ; Sat, 14 Aug 2004 02:03:56 +0200 Received: from [81.107.63.30] by mta10-svc.ntlworld.com (InterMail vM.4.01.03.37 201-229-121-137-20020806) with ESMTP id <20040814000243.NHAP340.mta10-svc.ntlworld.com@[81.107.63.30]> for ; Sat, 14 Aug 2004 01:02:43 +0100 Message-ID: <411D56EC.2070301@ntlworld.com> Date: Sat, 14 Aug 2004 01:03:56 +0100 From: "chris.danx" User-Agent: Mozilla Thunderbird 0.7.3 (X11/20040803) X-Accept-Language: en-us, en MIME-Version: 1.0 To: Caml Mailing List Subject: [Caml-list] Restricting Method Overriding/Redefinition in Subclass Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit X-Miltered: at nez-perce with ID 411D56EC.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Loop: caml-list@inria.fr X-Spam: no; 0.00; ntlworld:99 overriding:01 iterator:01 closures:01 iterating:01 closures:01 func:01 func:01 chris:01 chris:01 encode:01 inherit:01 inherit:01 closure:01 closure:01 Sender: owner-caml-list@pauillac.inria.fr Precedence: bulk Hi, Methods provide access control in the form of private or public methods, but I am in a position where I would like the client to extend some methods but not others, and would like some advice if possible. class type virtual base_class = object (self) method add_child (c : base_class) -> unit method remove_child (c : base_class) -> unit method remove_all_child (c : base_class) -> unit method private children : unit -> base_class iterator method virtual perform_action unit -> unit end;; perform_action is supposed to do something with the rendering state and call each of it's childrens perform_action methods in turn (unless it's a leaf). base_class is the base class for all objects in a scene graph. I have narrowed the behaviour of perform_action down to three possibilities. Either it does something before calling it's children, it does something after calling it's children or it does something before and after calling it's children. This leads either to one class with additional two methods (recode base_class to include pre and post ops) or three classes with either a pre or post call or both. To ensure objects don't do extra work I was considering the three class solution or a set of classes paramterised by closures which resolve to essentially the same thing. e.g. class type prechild_class = object(self) inherit base_class method virtual pre_op unit -> unit method perform_action unit -> unit end;; or (* pre_op_func is a typically a closure and essentially behaves like a hook. *) class type prechild_class (pre_op_func : unit -> unit) = object(self) inherit base_class ... method perform_action unit -> unit end;; Basically pre_op can be overridden to perform the desired function, with perform_action calling it before iterating over the children or a closure can be provided and called by perform_action. Is it possible to prevent the redefinition of perform_action by a subclass? If not I can live with it, but if there is a way it would serve to enforce the intended behaviour of the class. Namely that it should do what it needs to do and call it's children somewhere in perform_action. One could rely on the subclass to encode this behaviour, but it would be very easy for programmers to forget this which leads to a violation of what could be regarded as a class invariant. Perhaps a radically different solution is best? I chose an OO solution so that new classes could be trivially added to the system. It just occured to me that the same functionality can be provided with records where all the operations are closures. Pass in the relevant functions to a function and get a closure with all the operations of the original class. It's entirely possible I'm over analysing the problem and should use something simpler as I've done that before on more than one occassion. Any advice is welcome. Cheers, Chris ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners