4 >The class type extension</TITLE
7 CONTENT="Modular DocBook HTML Stylesheet Version 1.46"><LINK
9 TITLE="The PXP user's guide"
10 HREF="index.html"><LINK
12 TITLE="The objects representing the document"
13 HREF="c893.html"><LINK
15 TITLE="The class type node"
16 HREF="x939.html"><LINK
18 TITLE="Details of the mapping from XML text to the tree representation"
19 HREF="x1496.html"><LINK
22 HREF="markup.css"></HEAD
41 >The PXP user's guide</TH
56 >Chapter 3. The objects representing the document</TD
76 >3.3. The class type <TT
83 CLASS="PROGRAMLISTING"
84 >class type [ 'node ] extension =
87 (* "clone" should return an exact deep copy of the object. *)
89 (* "node" returns the corresponding node of this extension. This method
90 * intended to return exactly what previously has been set by "set_node".
92 method set_node : 'node -> unit
93 (* "set_node" is invoked once the extension is associated to a new
99 This is the type of classes used for node extensions. For every node of the
100 document tree, there is not only the <TT
107 > object. The latter has minimal
108 functionality; it has only the necessary methods to be attached to the node
109 object containing the details of the node instance. The extension object is
110 called extension because its purpose is extensibility.</P
112 >For some reasons, it is impossible to derive the
123 >) such that the subclasses can be extended by new
125 subclassing nodes is a great feature, because it allows the user to provide
126 different classes for different types of nodes. The extension objects are a
127 workaround that is as powerful as direct subclassing, the costs are
128 some notation overhead.</P
132 NAME="EXTENSION-GENERAL"
136 >Figure 3-6. The structure of nodes and extensions</B
140 SRC="pic/extension_general.gif"></P
143 >The picture shows how the nodes and extensions are linked
144 together. Every node has a reference to its extension, and every extension has
145 a reference to its node. The methods <TT
152 > follow these references; a typical phrase is
155 CLASS="PROGRAMLISTING"
156 >self # node # attribute "xy"</PRE
159 to get the value of an attribute from a method defined in the extension object;
163 CLASS="PROGRAMLISTING"
165 (fun n -> n # extension # my_method ...)</PRE
168 to iterate over the subnodes and to call <TT
172 corresponding extension objects.</P
174 >Note that extension objects do not have references to subnodes
175 (or "subextensions") themselves; in order to get one of the children of an
176 extension you must first go to the node object, then get the child node, and
177 finally reach the extension that is logically the child of the extension you
185 >3.3.1. How to define an extension class</A
188 >At minimum, you must define the methods
199 > such that your class is compatible with the type
207 during the initialization of the node, or after a node has been cloned; the
208 node object invokes <TT
211 > on the extension object to tell
212 it that this node is now the object the extension is linked to. The extension
213 must return the node object passed as argument of <TT
220 > method is called.</P
225 > method must return a copy of the
226 extension object; at least the object itself must be duplicated, but if
227 required, the copy should deeply duplicate all objects and values that are
228 referred by the extension, too. Whether this is required, depends on the
232 > is invoked by the node object when one of
233 its cloning methods is called.</P
235 >A good starting point for an extension class:
238 CLASS="PROGRAMLISTING"
239 >class custom_extension =
242 val mutable node = (None : custom_extension node option)
244 method clone = {< >}
258 This class is compatible with <TT
262 defining such a class is, of course, adding further methods; and you can do it
263 without restriction. </P
265 >Often, you want not only one extension class. In this case,
266 it is the simplest way that all your classes (for one kind of document) have
267 the same type (with respect to the interface; i.e. it does not matter if your
268 classes differ in the defined private methods and instance variables, but
269 public methods count). This approach avoids lots of coercions and problems with
270 type incompatibilities. It is simple to implement:
273 CLASS="PROGRAMLISTING"
274 >class custom_extension =
276 val mutable node = (None : custom_extension node option)
278 method clone = ... (* see above *)
279 method node = ... (* see above *)
280 method set_node n = ... (* see above *)
282 method virtual my_method1 : ...
283 method virtual my_method2 : ...
287 class custom_extension_kind_A =
289 inherit custom_extension
291 method my_method1 = ...
292 method my_method2 = ...
295 class custom_extension_kind_B =
297 inherit custom_extension
299 method my_method1 = ...
300 method my_method2 = ...
304 If a class does not need a method (e.g. because it does not make sense, or it
305 would violate some important condition), it is possible to define the method
306 and to always raise an exception when the method is invoked
312 >The latter is a strong recommendation: do not try to further
313 specialize the types of extension objects. It is difficult, sometimes even
314 impossible, and almost never worth-while.</P
322 >3.3.2. How to bind extension classes to element types</A
325 >Once you have defined your extension classes, you can bind them
326 to element types. The simplest case is that you have only one class and that
327 this class is to be always used. The parsing functions in the module
335 can be customized. If your single class has the name <TT
339 this argument should be
342 CLASS="PROGRAMLISTING"
345 ~data_exemplar: (new data_impl c)
346 ~default_element_exemplar: (new element_impl c)
351 This means that data nodes will be created from the exemplar passed by
352 ~data_exemplar and that all element nodes will be made from the exemplar
353 specified by ~default_element_exemplar. In ~element_alist, you can
354 pass that different exemplars are to be used for different element types; but
355 this is an optional feature. If you do not need it, pass the empty list.</P
357 >Remember that an exemplar is a (node, extension) pair that serves as pattern
358 when new nodes (and the corresponding extension objects) are added to the
359 document tree. In this case, the exemplar contains <TT
363 extension, and when nodes are created, the exemplar is cloned, and cloning
364 makes also a copy of <TT
367 > such that all nodes of the document
368 tree will have a copy of <TT
377 specific element types to specific exemplars; as exemplars may be instances of
378 different classes it is effectively possible to bind element types to
379 classes. For example, if the element type "p" is implemented by class "c_p",
380 and "q" is realized by "c_q", you can pass the following value:
383 CLASS="PROGRAMLISTING"
386 ~data_exemplar: (new data_impl c)
387 ~default_element_exemplar: (new element_impl c)
389 [ "p", new element_impl c_p;
390 "q", new element_impl c_q;
395 The extension object <TT
398 > is still used for all data nodes and
399 for all other element types.</P
458 >Details of the mapping from XML text to the tree representation</TD