1<!DOCTYPE html> 2<html> 3<head> 4<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> 5<meta name="generator" content="hevea 2.18"> 6<link rel="stylesheet" type="text/css" href="manual.css"> 7<title>Chapter 3  Objects in OCaml</title> 8</head> 9<body> 10<a href="moduleexamples.html"><img src="previous_motif.gif" alt="Previous"></a> 11<a href="index.html"><img src="contents_motif.gif" alt="Up"></a> 12<a href="lablexamples.html"><img src="next_motif.gif" alt="Next"></a> 13<hr> 14<h1 class="chapter" id="sec23">Chapter 3  Objects in OCaml</h1> 15<ul> 16<li><a href="objectexamples.html#sec24">3.1  Classes and objects</a> 17</li><li><a href="objectexamples.html#sec25">3.2  Immediate objects</a> 18</li><li><a href="objectexamples.html#sec26">3.3  Reference to self</a> 19</li><li><a href="objectexamples.html#sec27">3.4  Initializers</a> 20</li><li><a href="objectexamples.html#sec28">3.5  Virtual methods</a> 21</li><li><a href="objectexamples.html#sec29">3.6  Private methods</a> 22</li><li><a href="objectexamples.html#sec30">3.7  Class interfaces</a> 23</li><li><a href="objectexamples.html#sec31">3.8  Inheritance</a> 24</li><li><a href="objectexamples.html#sec32">3.9  Multiple inheritance</a> 25</li><li><a href="objectexamples.html#sec33">3.10  Parameterized classes</a> 26</li><li><a href="objectexamples.html#sec34">3.11  Polymorphic methods</a> 27</li><li><a href="objectexamples.html#sec35">3.12  Using coercions</a> 28</li><li><a href="objectexamples.html#sec36">3.13  Functional objects</a> 29</li><li><a href="objectexamples.html#sec37">3.14  Cloning objects</a> 30</li><li><a href="objectexamples.html#sec38">3.15  Recursive classes</a> 31</li><li><a href="objectexamples.html#sec39">3.16  Binary methods</a> 32</li><li><a href="objectexamples.html#sec40">3.17  Friends</a> 33</li></ul> 34<p> 35<a id="c:objectexamples"></a> 36 37</p><p> 38<span class="c009">(Chapter written by Jérôme Vouillon, Didier Rémy and Jacques Garrigue)</span></p><p><br> 39<br> 40</p><p>This chapter gives an overview of the object-oriented features of 41OCaml. Note that the relation between object, class and type 42in OCaml is very different from that in mainstream 43object-oriented languages like Java or C++, so that you should not 44assume that similar keywords mean the same thing.</p><p><a href="#ss%3Aclasses-and-objects">3.1</a> Classes and objects <br> 45<a href="#ss%3Aimmediate-objects">3.2</a> Immediate objects <br> 46<a href="#ss%3Areference-to-self">3.3</a> Reference to self <br> 47<a href="#ss%3Ainitializers">3.4</a> Initializers <br> 48<a href="#ss%3Avirtual-methods">3.5</a> Virtual methods <br> 49<a href="#ss%3Aprivate-methods">3.6</a> Private methods <br> 50<a href="#ss%3Aclass-interfaces">3.7</a> Class interfaces <br> 51<a href="#ss%3Ainheritance">3.8</a> Inheritance <br> 52<a href="#ss%3Amultiple-inheritance">3.9</a> Multiple inheritance <br> 53<a href="#ss%3Aparameterized-classes">3.10</a> Parameterized classes <br> 54<a href="#ss%3Apolymorphic-methods">3.11</a> Polymorphic methods <br> 55<a href="#ss%3Ausing-coercions">3.12</a> Using coercions <br> 56<a href="#ss%3Afunctional-objects">3.13</a> Functional objects <br> 57<a href="#ss%3Acloning-objects">3.14</a> Cloning objects <br> 58<a href="#ss%3Arecursive-classes">3.15</a> Recursive classes <br> 59<a href="#ss%3Abinary-methods">3.16</a> Binary methods <br> 60<a href="#ss%3Afriends">3.17</a> Friends <br> 61 62</p> 63<h2 class="section" id="sec24">3.1  Classes and objects</h2> 64<p> 65 66<a id="ss:classes-and-objects"></a></p><p>The class <span class="c003">point</span> below defines one instance variable <span class="c003">x</span> and two methods 67<span class="c003">get_x</span> and <span class="c003">move</span>. The initial value of the instance variable is <span class="c003">0</span>. 68The variable <span class="c003">x</span> is declared mutable, so the method <span class="c003">move</span> can change 69its value. 70</p><div class="caml-example"> 71<pre><div class="caml-input"> class point = 72 object 73 val mutable x = 0 74 method get_x = x 75 method move d = x <- x + d 76 end;; 77</div><div class="caml-output ok">class point : 78 object val mutable x : int method get_x : int method move : int -> unit end 79</div></pre> 80 81</div><p>We now create a new point <span class="c003">p</span>, instance of the <span class="c003">point</span> class. 82</p><div class="caml-example"> 83<pre><div class="caml-input"> let p = new point;; 84</div><div class="caml-output ok">val p : point = <obj> 85</div></pre> 86 87</div><p>Note that the type of <span class="c003">p</span> is <span class="c003">point</span>. This is an abbreviation 88automatically defined by the class definition above. It stands for the 89object type <span class="c003"><get_x : int; move : int -> unit></span>, listing the methods 90of class <span class="c003">point</span> along with their types.</p><p>We now invoke some methods to <span class="c003">p</span>: 91</p><div class="caml-example"> 92<pre><div class="caml-input"> p#get_x;; 93</div><div class="caml-output ok">- : int = 0 94</div></pre> 95 96<pre><div class="caml-input"> p#move 3;; 97</div><div class="caml-output ok">- : unit = () 98</div></pre> 99 100<pre><div class="caml-input"> p#get_x;; 101</div><div class="caml-output ok">- : int = 3 102</div></pre> 103 104</div><p>The evaluation of the body of a class only takes place at object 105creation time. Therefore, in the following example, the instance 106variable <span class="c003">x</span> is initialized to different values for two different 107objects. 108</p><div class="caml-example"> 109<pre><div class="caml-input"> let x0 = ref 0;; 110</div><div class="caml-output ok">val x0 : int ref = {contents = 0} 111</div></pre> 112 113<pre><div class="caml-input"> class point = 114 object 115 val mutable x = incr x0; !x0 116 method get_x = x 117 method move d = x <- x + d 118 end;; 119</div><div class="caml-output ok">class point : 120 object val mutable x : int method get_x : int method move : int -> unit end 121</div></pre> 122 123<pre><div class="caml-input"> new point#get_x;; 124</div><div class="caml-output ok">- : int = 1 125</div></pre> 126 127<pre><div class="caml-input"> new point#get_x;; 128</div><div class="caml-output ok">- : int = 2 129</div></pre> 130 131</div><p>The class <span class="c003">point</span> can also be abstracted over the initial values of 132the <span class="c003">x</span> coordinate. 133</p><div class="caml-example"> 134<pre><div class="caml-input"> class point = fun x_init -> 135 object 136 val mutable x = x_init 137 method get_x = x 138 method move d = x <- x + d 139 end;; 140</div><div class="caml-output ok">class point : 141 int -> 142 object val mutable x : int method get_x : int method move : int -> unit end 143</div></pre> 144 145</div><p>Like in function definitions, the definition above can be 146abbreviated as: 147</p><div class="caml-example"> 148<pre><div class="caml-input"> class point x_init = 149 object 150 val mutable x = x_init 151 method get_x = x 152 method move d = x <- x + d 153 end;; 154</div><div class="caml-output ok">class point : 155 int -> 156 object val mutable x : int method get_x : int method move : int -> unit end 157</div></pre> 158 159</div><p>An instance of the class <span class="c003">point</span> is now a function that expects an 160initial parameter to create a point object: 161</p><div class="caml-example"> 162<pre><div class="caml-input"> new point;; 163</div><div class="caml-output ok">- : int -> point = <fun> 164</div></pre> 165 166<pre><div class="caml-input"> let p = new point 7;; 167</div><div class="caml-output ok">val p : point = <obj> 168</div></pre> 169 170</div><p>The parameter <span class="c003">x_init</span> is, of course, visible in the whole body of the 171definition, including methods. For instance, the method <span class="c003">get_offset</span> 172in the class below returns the position of the object relative to its 173initial position. 174</p><div class="caml-example"> 175<pre><div class="caml-input"> class point x_init = 176 object 177 val mutable x = x_init 178 method get_x = x 179 method get_offset = x - x_init 180 method move d = x <- x + d 181 end;; 182</div><div class="caml-output ok">class point : 183 int -> 184 object 185 val mutable x : int 186 method get_offset : int 187 method get_x : int 188 method move : int -> unit 189 end 190</div></pre> 191 192</div><p>Expressions can be evaluated and bound before defining the object body 193of the class. This is useful to enforce invariants. For instance, 194points can be automatically adjusted to the nearest point on a grid, 195as follows: 196</p><div class="caml-example"> 197<pre><div class="caml-input"> class adjusted_point x_init = 198 let origin = (x_init / 10) * 10 in 199 object 200 val mutable x = origin 201 method get_x = x 202 method get_offset = x - origin 203 method move d = x <- x + d 204 end;; 205</div><div class="caml-output ok">class adjusted_point : 206 int -> 207 object 208 val mutable x : int 209 method get_offset : int 210 method get_x : int 211 method move : int -> unit 212 end 213</div></pre> 214 215</div><p>(One could also raise an exception if the <span class="c003">x_init</span> coordinate is not 216on the grid.) In fact, the same effect could here be obtained by 217calling the definition of class <span class="c003">point</span> with the value of the 218<span class="c003">origin</span>. 219</p><div class="caml-example"> 220<pre><div class="caml-input"> class adjusted_point x_init = point ((x_init / 10) * 10);; 221</div><div class="caml-output ok">class adjusted_point : int -> point 222</div></pre> 223 224</div><p>An alternate solution would have been to define the adjustment in 225a special allocation function: 226</p><div class="caml-example"> 227<pre><div class="caml-input"> let new_adjusted_point x_init = new point ((x_init / 10) * 10);; 228</div><div class="caml-output ok">val new_adjusted_point : int -> point = <fun> 229</div></pre> 230 231</div><p>However, the former pattern is generally more appropriate, since 232the code for adjustment is part of the definition of the class and will be 233inherited.</p><p>This ability provides class constructors as can be found in other 234languages. Several constructors can be defined this way to build objects of 235the same class but with different initialization patterns; an 236alternative is to use initializers, as described below in section 237<a href="#ss%3Ainitializers">3.4</a>.</p> 238<h2 class="section" id="sec25">3.2  Immediate objects</h2> 239<p> 240 241<a id="ss:immediate-objects"></a></p><p>There is another, more direct way to create an object: create it 242without going through a class.</p><p>The syntax is exactly the same as for class expressions, but the 243result is a single object rather than a class. All the constructs 244described in the rest of this section also apply to immediate objects. 245</p><div class="caml-example"> 246<pre><div class="caml-input"> let p = 247 object 248 val mutable x = 0 249 method get_x = x 250 method move d = x <- x + d 251 end;; 252</div><div class="caml-output ok">val p : < get_x : int; move : int -> unit > = <obj> 253</div></pre> 254 255<pre><div class="caml-input"> p#get_x;; 256</div><div class="caml-output ok">- : int = 0 257</div></pre> 258 259<pre><div class="caml-input"> p#move 3;; 260</div><div class="caml-output ok">- : unit = () 261</div></pre> 262 263<pre><div class="caml-input"> p#get_x;; 264</div><div class="caml-output ok">- : int = 3 265</div></pre> 266 267</div><p>Unlike classes, which cannot be defined inside an expression, 268immediate objects can appear anywhere, using variables from their 269environment. 270</p><div class="caml-example"> 271<pre><div class="caml-input"> let minmax x y = 272 if x < y then object method min = x method max = y end 273 else object method min = y method max = x end;; 274</div><div class="caml-output ok">val minmax : 'a -> 'a -> < max : 'a; min : 'a > = <fun> 275</div></pre> 276 277</div><p>Immediate objects have two weaknesses compared to classes: their types 278are not abbreviated, and you cannot inherit from them. But these two 279weaknesses can be advantages in some situations, as we will see 280in sections <a href="#ss%3Areference-to-self">3.3</a> and <a href="#ss%3Aparameterized-classes">3.10</a>.</p> 281<h2 class="section" id="sec26">3.3  Reference to self</h2> 282<p> 283 284<a id="ss:reference-to-self"></a></p><p>A method or an initializer can send messages to self (that is, 285the current object). For that, self must be explicitly bound, here to 286the variable <span class="c003">s</span> (<span class="c003">s</span> could be any identifier, even though we will 287often choose the name <span class="c003">self</span>.) 288</p><div class="caml-example"> 289<pre><div class="caml-input"> class printable_point x_init = 290 object (s) 291 val mutable x = x_init 292 method get_x = x 293 method move d = x <- x + d 294 method print = print_int s#get_x 295 end;; 296</div><div class="caml-output ok">class printable_point : 297 int -> 298 object 299 val mutable x : int 300 method get_x : int 301 method move : int -> unit 302 method print : unit 303 end 304</div></pre> 305 306<pre><div class="caml-input"> let p = new printable_point 7;; 307</div><div class="caml-output ok">val p : printable_point = <obj> 308</div></pre> 309 310<pre><div class="caml-input"> p#print;; 311</div><div class="caml-output ok">7- : unit = () 312</div></pre> 313 314</div><p>Dynamically, the variable <span class="c003">s</span> is bound at the invocation of a method. In 315particular, when the class <span class="c003">printable_point</span> is inherited, the variable 316<span class="c003">s</span> will be correctly bound to the object of the subclass.</p><p>A common problem with self is that, as its type may be extended in 317subclasses, you cannot fix it in advance. Here is a simple example. 318</p><div class="caml-example"> 319<pre><div class="caml-input"> let ints = ref [];; 320</div><div class="caml-output ok">val ints : '_a list ref = {contents = []} 321</div></pre> 322 323<pre><div class="caml-input"> class my_int = 324 object (self) 325 method n = 1 326 method register = ints := <U>self</U> :: !ints 327 end ;; 328</div><div class="caml-output error">Error: This expression has type < n : int; register : 'a; .. > 329 but an expression was expected of type 'b 330 Self type cannot escape its class 331</div></pre> 332 333</div><p>You can ignore the first two lines of the error message. What matters 334is the last one: putting self into an external reference would make it 335impossible to extend it through inheritance. 336We will see in section <a href="#ss%3Ausing-coercions">3.12</a> a workaround to this 337problem. 338Note however that, since immediate objects are not extensible, the 339problem does not occur with them. 340</p><div class="caml-example"> 341<pre><div class="caml-input"> let my_int = 342 object (self) 343 method n = 1 344 method register = ints := self :: !ints 345 end;; 346</div><div class="caml-output ok">val my_int : < n : int; register : unit > = <obj> 347</div></pre> 348 349</div> 350<h2 class="section" id="sec27">3.4  Initializers</h2> 351<p> 352 353<a id="ss:initializers"></a></p><p>Let-bindings within class definitions are evaluated before the object 354is constructed. It is also possible to evaluate an expression 355immediately after the object has been built. Such code is written as 356an anonymous hidden method called an initializer. Therefore, it can 357access self and the instance variables. 358</p><div class="caml-example"> 359<pre><div class="caml-input"> class printable_point x_init = 360 let origin = (x_init / 10) * 10 in 361 object (self) 362 val mutable x = origin 363 method get_x = x 364 method move d = x <- x + d 365 method print = print_int self#get_x 366 initializer print_string "new point at "; self#print; print_newline () 367 end;; 368</div><div class="caml-output ok">class printable_point : 369 int -> 370 object 371 val mutable x : int 372 method get_x : int 373 method move : int -> unit 374 method print : unit 375 end 376</div></pre> 377 378<pre><div class="caml-input"> let p = new printable_point 17;; 379</div><div class="caml-output ok">new point at 10 380val p : printable_point = <obj> 381</div></pre> 382 383</div><p>Initializers cannot be overridden. On the contrary, all initializers are 384evaluated sequentially. 385Initializers are particularly useful to enforce invariants. 386Another example can be seen in section <a href="advexamples.html#ss%3Abank-accounts">5.1</a>.</p> 387<h2 class="section" id="sec28">3.5  Virtual methods</h2> 388<p> 389 390<a id="ss:virtual-methods"></a></p><p>It is possible to declare a method without actually defining it, using 391the keyword <span class="c003">virtual</span>. This method will be provided later in 392subclasses. A class containing virtual methods must be flagged 393<span class="c003">virtual</span>, and cannot be instantiated (that is, no object of this class 394can be created). It still defines type abbreviations (treating virtual methods 395as other methods.) 396</p><div class="caml-example"> 397<pre><div class="caml-input"> class virtual abstract_point x_init = 398 object (self) 399 method virtual get_x : int 400 method get_offset = self#get_x - x_init 401 method virtual move : int -> unit 402 end;; 403</div><div class="caml-output ok">class virtual abstract_point : 404 int -> 405 object 406 method get_offset : int 407 method virtual get_x : int 408 method virtual move : int -> unit 409 end 410</div></pre> 411 412<pre><div class="caml-input"> class point x_init = 413 object 414 inherit abstract_point x_init 415 val mutable x = x_init 416 method get_x = x 417 method move d = x <- x + d 418 end;; 419</div><div class="caml-output ok">class point : 420 int -> 421 object 422 val mutable x : int 423 method get_offset : int 424 method get_x : int 425 method move : int -> unit 426 end 427</div></pre> 428 429</div><p>Instance variables can also be declared as virtual, with the same effect 430as with methods. 431</p><div class="caml-example"> 432<pre><div class="caml-input"> class virtual abstract_point2 = 433 object 434 val mutable virtual x : int 435 method move d = x <- x + d 436 end;; 437</div><div class="caml-output ok">class virtual abstract_point2 : 438 object val mutable virtual x : int method move : int -> unit end 439</div></pre> 440 441<pre><div class="caml-input"> class point2 x_init = 442 object 443 inherit abstract_point2 444 val mutable x = x_init 445 method get_offset = x - x_init 446 end;; 447</div><div class="caml-output ok">class point2 : 448 int -> 449 object 450 val mutable x : int 451 method get_offset : int 452 method move : int -> unit 453 end 454</div></pre> 455 456</div> 457<h2 class="section" id="sec29">3.6  Private methods</h2> 458<p> 459 460<a id="ss:private-methods"></a></p><p>Private methods are methods that do not appear in object interfaces. 461They can only be invoked from other methods of the same object. 462</p><div class="caml-example"> 463<pre><div class="caml-input"> class restricted_point x_init = 464 object (self) 465 val mutable x = x_init 466 method get_x = x 467 method private move d = x <- x + d 468 method bump = self#move 1 469 end;; 470</div><div class="caml-output ok">class restricted_point : 471 int -> 472 object 473 val mutable x : int 474 method bump : unit 475 method get_x : int 476 method private move : int -> unit 477 end 478</div></pre> 479 480<pre><div class="caml-input"> let p = new restricted_point 0;; 481</div><div class="caml-output ok">val p : restricted_point = <obj> 482</div></pre> 483 484<pre><div class="caml-input"> <U>p</U>#move 10 ;; 485</div><div class="caml-output error">Error: This expression has type restricted_point 486 It has no method move 487</div></pre> 488 489<pre><div class="caml-input"> p#bump;; 490</div><div class="caml-output ok">- : unit = () 491</div></pre> 492 493</div><p>Note that this is not the same thing as private and protected methods 494in Java or C++, which can be called from other objects of the same 495class. This is a direct consequence of the independence between types 496and classes in OCaml: two unrelated classes may produce 497objects of the same type, and there is no way at the type level to 498ensure that an object comes from a specific class. However a possible 499encoding of friend methods is given in section <a href="#ss%3Afriends">3.17</a>.</p><p>Private methods are inherited (they are by default visible in subclasses), 500unless they are hidden by signature matching, as described below.</p><p>Private methods can be made public in a subclass. 501</p><div class="caml-example"> 502<pre><div class="caml-input"> class point_again x = 503 object (self) 504 inherit restricted_point x 505 method virtual move : _ 506 end;; 507</div><div class="caml-output ok">class point_again : 508 int -> 509 object 510 val mutable x : int 511 method bump : unit 512 method get_x : int 513 method move : int -> unit 514 end 515</div></pre> 516 517</div><p>The annotation <span class="c003">virtual</span> here is only used to mention a method without 518providing its definition. Since we didn’t add the <span class="c003">private</span> 519annotation, this makes the method public, keeping the original 520definition.</p><p>An alternative definition is 521</p><div class="caml-example"> 522<pre><div class="caml-input"> class point_again x = 523 object (self : < move : _; ..> ) 524 inherit restricted_point x 525 end;; 526</div><div class="caml-output ok">class point_again : 527 int -> 528 object 529 val mutable x : int 530 method bump : unit 531 method get_x : int 532 method move : int -> unit 533 end 534</div></pre> 535 536</div><p>The constraint on self’s type is requiring a public <span class="c003">move</span> method, and 537this is sufficient to override <span class="c003">private</span>.</p><p>One could think that a private method should remain private in a subclass. 538However, since the method is visible in a subclass, it is always possible 539to pick its code and define a method of the same name that runs that 540code, so yet another (heavier) solution would be: 541</p><div class="caml-example"> 542<pre><div class="caml-input"> class point_again x = 543 object 544 inherit restricted_point x as super 545 method move = super#move 546 end;; 547</div><div class="caml-output ok">class point_again : 548 int -> 549 object 550 val mutable x : int 551 method bump : unit 552 method get_x : int 553 method move : int -> unit 554 end 555</div></pre> 556 557</div><p>Of course, private methods can also be virtual. Then, the keywords must 558appear in this order <span class="c003">method private virtual</span>.</p> 559<h2 class="section" id="sec30">3.7  Class interfaces</h2> 560<p> 561 562<a id="ss:class-interfaces"></a></p><p>Class interfaces are inferred from class definitions. They may also 563be defined directly and used to restrict the type of a class. Like class 564declarations, they also define a new type abbreviation. 565</p><div class="caml-example"> 566<pre><div class="caml-input"> class type restricted_point_type = 567 object 568 method get_x : int 569 method bump : unit 570 end;; 571</div><div class="caml-output ok">class type restricted_point_type = 572 object method bump : unit method get_x : int end 573</div></pre> 574 575<pre><div class="caml-input"> fun (x : restricted_point_type) -> x;; 576</div><div class="caml-output ok">- : restricted_point_type -> restricted_point_type = <fun> 577</div></pre> 578 579</div><p>In addition to program documentation, class interfaces can be used to 580constrain the type of a class. Both concrete instance variables and concrete 581private methods can be hidden by a class type constraint. Public 582methods and virtual members, however, cannot. 583</p><div class="caml-example"> 584<pre><div class="caml-input"> class restricted_point' x = (restricted_point x : restricted_point_type);; 585</div><div class="caml-output ok">class restricted_point' : int -> restricted_point_type 586</div></pre> 587 588</div><p>Or, equivalently: 589</p><div class="caml-example"> 590<pre><div class="caml-input"> class restricted_point' = (restricted_point : int -> restricted_point_type);; 591</div><div class="caml-output ok">class restricted_point' : int -> restricted_point_type 592</div></pre> 593 594</div><p>The interface of a class can also be specified in a module 595signature, and used to restrict the inferred signature of a module. 596</p><div class="caml-example"> 597<pre><div class="caml-input"> module type POINT = sig 598 class restricted_point' : int -> 599 object 600 method get_x : int 601 method bump : unit 602 end 603 end;; 604</div><div class="caml-output ok">module type POINT = 605 sig 606 class restricted_point' : 607 int -> object method bump : unit method get_x : int end 608 end 609</div></pre> 610 611<pre><div class="caml-input"> module Point : POINT = struct 612 class restricted_point' = restricted_point 613 end;; 614</div><div class="caml-output ok">module Point : POINT 615</div></pre> 616 617</div> 618<h2 class="section" id="sec31">3.8  Inheritance</h2> 619<p> 620 621<a id="ss:inheritance"></a></p><p>We illustrate inheritance by defining a class of colored points that 622inherits from the class of points. This class has all instance 623variables and all methods of class <span class="c003">point</span>, plus a new instance 624variable <span class="c003">c</span> and a new method <span class="c003">color</span>. 625</p><div class="caml-example"> 626<pre><div class="caml-input"> class colored_point x (c : string) = 627 object 628 inherit point x 629 val c = c 630 method color = c 631 end;; 632</div><div class="caml-output ok">class colored_point : 633 int -> 634 string -> 635 object 636 val c : string 637 val mutable x : int 638 method color : string 639 method get_offset : int 640 method get_x : int 641 method move : int -> unit 642 end 643</div></pre> 644 645<pre><div class="caml-input"> let p' = new colored_point 5 "red";; 646</div><div class="caml-output ok">val p' : colored_point = <obj> 647</div></pre> 648 649<pre><div class="caml-input"> p'#get_x, p'#color;; 650</div><div class="caml-output ok">- : int * string = (5, "red") 651</div></pre> 652 653</div><p>A point and a colored point have incompatible types, since a point has 654no method <span class="c003">color</span>. However, the function <span class="c003">get_x</span> below is a generic 655function applying method <span class="c003">get_x</span> to any object <span class="c003">p</span> that has this 656method (and possibly some others, which are represented by an ellipsis 657in the type). Thus, it applies to both points and colored points. 658</p><div class="caml-example"> 659<pre><div class="caml-input"> let get_succ_x p = p#get_x + 1;; 660</div><div class="caml-output ok">val get_succ_x : < get_x : int; .. > -> int = <fun> 661</div></pre> 662 663<pre><div class="caml-input"> get_succ_x p + get_succ_x p';; 664</div><div class="caml-output ok">- : int = 8 665</div></pre> 666 667</div><p>Methods need not be declared previously, as shown by the example: 668</p><div class="caml-example"> 669<pre><div class="caml-input"> let set_x p = p#set_x;; 670</div><div class="caml-output ok">val set_x : < set_x : 'a; .. > -> 'a = <fun> 671</div></pre> 672 673<pre><div class="caml-input"> let incr p = set_x p (get_succ_x p);; 674</div><div class="caml-output ok">val incr : < get_x : int; set_x : int -> 'a; .. > -> 'a = <fun> 675</div></pre> 676 677</div> 678<h2 class="section" id="sec32">3.9  Multiple inheritance</h2> 679<p> 680 681<a id="ss:multiple-inheritance"></a></p><p>Multiple inheritance is allowed. Only the last definition of a method 682is kept: the redefinition in a subclass of a method that was visible in 683the parent class overrides the definition in the parent class. 684Previous definitions of a method can be reused by binding the related 685ancestor. Below, <span class="c003">super</span> is bound to the ancestor <span class="c003">printable_point</span>. 686The name <span class="c003">super</span> is a pseudo value identifier that can only be used to 687invoke a super-class method, as in <span class="c003">super#print</span>. 688</p><div class="caml-example"> 689<pre><div class="caml-input"> class printable_colored_point y c = 690 object (self) 691 val c = c 692 method color = c 693 inherit printable_point y as super 694 method print = 695 print_string "("; 696 super#print; 697 print_string ", "; 698 print_string (self#color); 699 print_string ")" 700 end;; 701</div><div class="caml-output ok">class printable_colored_point : 702 int -> 703 string -> 704 object 705 val c : string 706 val mutable x : int 707 method color : string 708 method get_x : int 709 method move : int -> unit 710 method print : unit 711 end 712</div></pre> 713 714<pre><div class="caml-input"> let p' = new printable_colored_point 17 "red";; 715</div><div class="caml-output ok">new point at (10, red) 716val p' : printable_colored_point = <obj> 717</div></pre> 718 719<pre><div class="caml-input"> p'#print;; 720</div><div class="caml-output ok">(10, red)- : unit = () 721</div></pre> 722 723</div><p>A private method that has been hidden in the parent class is no longer 724visible, and is thus not overridden. Since initializers are treated as 725private methods, all initializers along the class hierarchy are evaluated, 726in the order they are introduced.</p> 727<h2 class="section" id="sec33">3.10  Parameterized classes</h2> 728<p> 729 730<a id="ss:parameterized-classes"></a></p><p>Reference cells can be implemented as objects. 731The naive definition fails to typecheck: 732</p><div class="caml-example"> 733<pre><div class="caml-input"> <U>class oref x_init = 734 object 735 val mutable x = x_init 736 method get = x 737 method set y = x <- y 738 end</U>;; 739</div><div class="caml-output error">Error: Some type variables are unbound in this type: 740 class oref : 741 'a -> 742 object 743 val mutable x : 'a 744 method get : 'a 745 method set : 'a -> unit 746 end 747 The method get has type 'a where 'a is unbound 748</div></pre> 749 750</div><p>The reason is that at least one of the methods has a polymorphic type 751(here, the type of the value stored in the reference cell), thus 752either the class should be parametric, or the method type should be 753constrained to a monomorphic type. A monomorphic instance of the class could 754be defined by: 755</p><div class="caml-example"> 756<pre><div class="caml-input"> class oref (x_init:int) = 757 object 758 val mutable x = x_init 759 method get = x 760 method set y = x <- y 761 end;; 762</div><div class="caml-output ok">class oref : 763 int -> 764 object val mutable x : int method get : int method set : int -> unit end 765</div></pre> 766 767</div><p>Note that since immediate objects do not define a class type, they have 768no such restriction. 769</p><div class="caml-example"> 770<pre><div class="caml-input"> let new_oref x_init = 771 object 772 val mutable x = x_init 773 method get = x 774 method set y = x <- y 775 end;; 776</div><div class="caml-output ok">val new_oref : 'a -> < get : 'a; set : 'a -> unit > = <fun> 777</div></pre> 778 779</div><p>On the other hand, a class for polymorphic references must explicitly 780list the type parameters in its declaration. Class type parameters are 781listed between <span class="c003">[</span> and <span class="c003">]</span>. The type parameters must also be 782bound somewhere in the class body by a type constraint. 783</p><div class="caml-example"> 784<pre><div class="caml-input"> class ['a] oref x_init = 785 object 786 val mutable x = (x_init : 'a) 787 method get = x 788 method set y = x <- y 789 end;; 790</div><div class="caml-output ok">class ['a] oref : 791 'a -> object val mutable x : 'a method get : 'a method set : 'a -> unit end 792</div></pre> 793 794<pre><div class="caml-input"> let r = new oref 1 in r#set 2; (r#get);; 795</div><div class="caml-output ok">- : int = 2 796</div></pre> 797 798</div><p>The type parameter in the declaration may actually be constrained in the 799body of the class definition. In the class type, the actual value of 800the type parameter is displayed in the <span class="c003">constraint</span> clause. 801</p><div class="caml-example"> 802<pre><div class="caml-input"> class ['a] oref_succ (x_init:'a) = 803 object 804 val mutable x = x_init + 1 805 method get = x 806 method set y = x <- y 807 end;; 808</div><div class="caml-output ok">class ['a] oref_succ : 809 'a -> 810 object 811 constraint 'a = int 812 val mutable x : int 813 method get : int 814 method set : int -> unit 815 end 816</div></pre> 817 818</div><p>Let us consider a more complex example: define a circle, whose center 819may be any kind of point. We put an additional type 820constraint in method <span class="c003">move</span>, since no free variables must remain 821unaccounted for by the class type parameters. 822</p><div class="caml-example"> 823<pre><div class="caml-input"> class ['a] circle (c : 'a) = 824 object 825 val mutable center = c 826 method center = center 827 method set_center c = center <- c 828 method move = (center#move : int -> unit) 829 end;; 830</div><div class="caml-output ok">class ['a] circle : 831 'a -> 832 object 833 constraint 'a = < move : int -> unit; .. > 834 val mutable center : 'a 835 method center : 'a 836 method move : int -> unit 837 method set_center : 'a -> unit 838 end 839</div></pre> 840 841</div><p>An alternate definition of <span class="c003">circle</span>, using a <span class="c003">constraint</span> clause in 842the class definition, is shown below. The type <span class="c003">#point</span> used below in 843the <span class="c003">constraint</span> clause is an abbreviation produced by the definition 844of class <span class="c003">point</span>. This abbreviation unifies with the type of any 845object belonging to a subclass of class <span class="c003">point</span>. It actually expands to 846<span class="c003">< get_x : int; move : int -> unit; .. ></span>. This leads to the following 847alternate definition of <span class="c003">circle</span>, which has slightly stronger 848constraints on its argument, as we now expect <span class="c003">center</span> to have a 849method <span class="c003">get_x</span>. 850</p><div class="caml-example"> 851<pre><div class="caml-input"> class ['a] circle (c : 'a) = 852 object 853 constraint 'a = #point 854 val mutable center = c 855 method center = center 856 method set_center c = center <- c 857 method move = center#move 858 end;; 859</div><div class="caml-output ok">class ['a] circle : 860 'a -> 861 object 862 constraint 'a = #point 863 val mutable center : 'a 864 method center : 'a 865 method move : int -> unit 866 method set_center : 'a -> unit 867 end 868</div></pre> 869 870</div><p>The class <span class="c003">colored_circle</span> is a specialized version of class 871<span class="c003">circle</span> that requires the type of the center to unify with 872<span class="c003">#colored_point</span>, and adds a method <span class="c003">color</span>. Note that when specializing a 873parameterized class, the instance of type parameter must always be 874explicitly given. It is again written between <span class="c003">[</span> and <span class="c003">]</span>. 875</p><div class="caml-example"> 876<pre><div class="caml-input"> class ['a] colored_circle c = 877 object 878 constraint 'a = #colored_point 879 inherit ['a] circle c 880 method color = center#color 881 end;; 882</div><div class="caml-output ok">class ['a] colored_circle : 883 'a -> 884 object 885 constraint 'a = #colored_point 886 val mutable center : 'a 887 method center : 'a 888 method color : string 889 method move : int -> unit 890 method set_center : 'a -> unit 891 end 892</div></pre> 893 894</div> 895<h2 class="section" id="sec34">3.11  Polymorphic methods</h2> 896<p> 897 898<a id="ss:polymorphic-methods"></a></p><p>While parameterized classes may be polymorphic in their contents, they 899are not enough to allow polymorphism of method use.</p><p>A classical example is defining an iterator. 900</p><div class="caml-example"> 901<pre><div class="caml-input"> List.fold_left;; 902</div><div class="caml-output ok">- : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun> 903</div></pre> 904 905<pre><div class="caml-input"> class ['a] intlist (l : int list) = 906 object 907 method empty = (l = []) 908 method fold f (accu : 'a) = List.fold_left f accu l 909 end;; 910</div><div class="caml-output ok">class ['a] intlist : 911 int list -> 912 object method empty : bool method fold : ('a -> int -> 'a) -> 'a -> 'a end 913</div></pre> 914 915</div><p>At first look, we seem to have a polymorphic iterator, however this 916does not work in practice. 917</p><div class="caml-example"> 918<pre><div class="caml-input"> let l = new intlist [1; 2; 3];; 919</div><div class="caml-output ok">val l : '_a intlist = <obj> 920</div></pre> 921 922<pre><div class="caml-input"> l#fold (fun x y -> x+y) 0;; 923</div><div class="caml-output ok">- : int = 6 924</div></pre> 925 926<pre><div class="caml-input"> l;; 927</div><div class="caml-output ok">- : int intlist = <obj> 928</div></pre> 929 930<pre><div class="caml-input"> l#fold (fun s x -> <U>s</U> ^ string_of_int x ^ " ") "" ;; 931</div><div class="caml-output error">Error: This expression has type int but an expression was expected of type 932 string 933</div></pre> 934 935</div><p>Our iterator works, as shows its first use for summation. However, 936since objects themselves are not polymorphic (only their constructors 937are), using the <span class="c003">fold</span> method fixes its type for this individual object. 938Our next attempt to use it as a string iterator fails.</p><p>The problem here is that quantification was wrongly located: it is 939not the class we want to be polymorphic, but the <span class="c003">fold</span> method. 940This can be achieved by giving an explicitly polymorphic type in the 941method definition. 942</p><div class="caml-example"> 943<pre><div class="caml-input"> class intlist (l : int list) = 944 object 945 method empty = (l = []) 946 method fold : 'a. ('a -> int -> 'a) -> 'a -> 'a = 947 fun f accu -> List.fold_left f accu l 948 end;; 949</div><div class="caml-output ok">class intlist : 950 int list -> 951 object method empty : bool method fold : ('a -> int -> 'a) -> 'a -> 'a end 952</div></pre> 953 954<pre><div class="caml-input"> let l = new intlist [1; 2; 3];; 955</div><div class="caml-output ok">val l : intlist = <obj> 956</div></pre> 957 958<pre><div class="caml-input"> l#fold (fun x y -> x+y) 0;; 959</div><div class="caml-output ok">- : int = 6 960</div></pre> 961 962<pre><div class="caml-input"> l#fold (fun s x -> s ^ string_of_int x ^ " ") "";; 963</div><div class="caml-output ok">- : string = "1 2 3 " 964</div></pre> 965 966</div><p>As you can see in the class type shown by the compiler, while 967polymorphic method types must be fully explicit in class definitions 968(appearing immediately after the method name), quantified type 969variables can be left implicit in class descriptions. Why require types 970to be explicit? The problem is that <span class="c003">(int -> int -> int) -> int -> int</span> would also be a valid type for <span class="c003">fold</span>, and it happens to be 971incompatible with the polymorphic type we gave (automatic 972instantiation only works for toplevel types variables, not for inner 973quantifiers, where it becomes an undecidable problem.) So the compiler 974cannot choose between those two types, and must be helped.</p><p>However, the type can be completely omitted in the class definition if 975it is already known, through inheritance or type constraints on self. 976Here is an example of method overriding. 977</p><div class="caml-example"> 978<pre><div class="caml-input"> class intlist_rev l = 979 object 980 inherit intlist l 981 method fold f accu = List.fold_left f accu (List.rev l) 982 end;; 983</div> 984</pre> 985 986</div><p>The following idiom separates description and definition. 987</p><div class="caml-example"> 988<pre><div class="caml-input"> class type ['a] iterator = 989 object method fold : ('b -> 'a -> 'b) -> 'b -> 'b end;; 990</div> 991</pre> 992 993<pre><div class="caml-input"> class intlist l = 994 object (self : int #iterator) 995 method empty = (l = []) 996 method fold f accu = List.fold_left f accu l 997 end;; 998</div> 999</pre> 1000 1001</div><p>Note here the <span class="c003">(self : int #iterator)</span> idiom, which ensures that this 1002object implements the interface <span class="c003">iterator</span>.</p><p>Polymorphic methods are called in exactly the same way as normal 1003methods, but you should be aware of some limitations of type 1004inference. Namely, a polymorphic method can only be called if its 1005type is known at the call site. Otherwise, the method will be assumed 1006to be monomorphic, and given an incompatible type. 1007</p><div class="caml-example"> 1008<pre><div class="caml-input"> let sum lst = lst#fold (fun x y -> x+y) 0;; 1009</div><div class="caml-output ok">val sum : < fold : (int -> int -> int) -> int -> 'a; .. > -> 'a = <fun> 1010</div></pre> 1011 1012<pre><div class="caml-input"> sum <U>l</U> ;; 1013</div><div class="caml-output error">Error: This expression has type intlist 1014 but an expression was expected of type 1015 < fold : (int -> int -> int) -> int -> 'a; .. > 1016 Types for method fold are incompatible 1017</div></pre> 1018 1019</div><p>The workaround is easy: you should put a type constraint on the 1020parameter. 1021</p><div class="caml-example"> 1022<pre><div class="caml-input"> let sum (lst : _ #iterator) = lst#fold (fun x y -> x+y) 0;; 1023</div><div class="caml-output ok">val sum : int #iterator -> int = <fun> 1024</div></pre> 1025 1026</div><p>Of course the constraint may also be an explicit method type. 1027Only occurences of quantified variables are required. 1028</p><div class="caml-example"> 1029<pre><div class="caml-input"> let sum lst = 1030 (lst : < fold : 'a. ('a -> _ -> 'a) -> 'a -> 'a; .. >)#fold (+) 0;; 1031</div><div class="caml-output ok">val sum : < fold : 'a. ('a -> int -> 'a) -> 'a -> 'a; .. > -> int = <fun> 1032</div></pre> 1033 1034</div><p>Another use of polymorphic methods is to allow some form of implicit 1035subtyping in method arguments. We have already seen in section 1036<a href="#ss%3Ainheritance">3.8</a> how some functions may be polymorphic in the 1037class of their argument. This can be extended to methods. 1038</p><div class="caml-example"> 1039<pre><div class="caml-input"> class type point0 = object method get_x : int end;; 1040</div><div class="caml-output ok">class type point0 = object method get_x : int end 1041</div></pre> 1042 1043<pre><div class="caml-input"> class distance_point x = 1044 object 1045 inherit point x 1046 method distance : 'a. (#point0 as 'a) -> int = 1047 fun other -> abs (other#get_x - x) 1048 end;; 1049</div><div class="caml-output ok">class distance_point : 1050 int -> 1051 object 1052 val mutable x : int 1053 method distance : #point0 -> int 1054 method get_offset : int 1055 method get_x : int 1056 method move : int -> unit 1057 end 1058</div></pre> 1059 1060<pre><div class="caml-input"> let p = new distance_point 3 in 1061 (p#distance (new point 8), p#distance (new colored_point 1 "blue"));; 1062</div><div class="caml-output ok">- : int * int = (5, 2) 1063</div></pre> 1064 1065</div><p>Note here the special syntax <span class="c003">(#point0 as 'a)</span> we have to use to 1066quantify the extensible part of <span class="c003">#point0</span>. As for the variable binder, 1067it can be omitted in class specifications. If you want polymorphism 1068inside object field it must be quantified independently. 1069</p><div class="caml-example"> 1070<pre><div class="caml-input"> class multi_poly = 1071 object 1072 method m1 : 'a. (< n1 : 'b. 'b -> 'b; .. > as 'a) -> _ = 1073 fun o -> o#n1 true, o#n1 "hello" 1074 method m2 : 'a 'b. (< n2 : 'b -> bool; .. > as 'a) -> 'b -> _ = 1075 fun o x -> o#n2 x 1076 end;; 1077</div><div class="caml-output ok">class multi_poly : 1078 object 1079 method m1 : < n1 : 'b. 'b -> 'b; .. > -> bool * string 1080 method m2 : < n2 : 'b -> bool; .. > -> 'b -> bool 1081 end 1082</div></pre> 1083 1084</div><p>In method <span class="c003">m1</span>, <span class="c003">o</span> must be an object with at least a method <span class="c003">n1</span>, 1085itself polymorphic. In method <span class="c003">m2</span>, the argument of <span class="c003">n2</span> and <span class="c003">x</span> must 1086have the same type, which is quantified at the same level as <span class="c003">'a</span>.</p> 1087<h2 class="section" id="sec35">3.12  Using coercions</h2> 1088<p> 1089 1090<a id="ss:using-coercions"></a></p><p>Subtyping is never implicit. There are, however, two ways to perform 1091subtyping. The most general construction is fully explicit: both the 1092domain and the codomain of the type coercion must be given.</p><p>We have seen that points and colored points have incompatible types. 1093For instance, they cannot be mixed in the same list. However, a 1094colored point can be coerced to a point, hiding its <span class="c003">color</span> method: 1095</p><div class="caml-example"> 1096<pre><div class="caml-input"> let colored_point_to_point cp = (cp : colored_point :> point);; 1097</div><div class="caml-output ok">val colored_point_to_point : colored_point -> point = <fun> 1098</div></pre> 1099 1100<pre><div class="caml-input"> let p = new point 3 and q = new colored_point 4 "blue";; 1101</div><div class="caml-output ok">val p : point = <obj> 1102val q : colored_point = <obj> 1103</div></pre> 1104 1105<pre><div class="caml-input"> let l = [p; (colored_point_to_point q)];; 1106</div><div class="caml-output ok">val l : point list = [<obj>; <obj>] 1107</div></pre> 1108 1109</div><p>An object of type <span class="c003">t</span> can be seen as an object of type <span class="c003">t'</span> 1110only if <span class="c003">t</span> is a subtype of <span class="c003">t'</span>. For instance, a point cannot be 1111seen as a colored point. 1112</p><div class="caml-example"> 1113<pre><div class="caml-input"> <U>(p : point :> colored_point)</U>;; 1114</div><div class="caml-output error">Error: Type point = < get_offset : int; get_x : int; move : int -> unit > 1115 is not a subtype of 1116 colored_point = 1117 < color : string; get_offset : int; get_x : int; 1118 move : int -> unit > 1119</div></pre> 1120 1121</div><p>Indeed, narrowing coercions without runtime checks would be unsafe. 1122Runtime type checks might raise exceptions, and they would require 1123the presence of type information at runtime, which is not the case in 1124the OCaml system. 1125For these reasons, there is no such operation available in the language.</p><p>Be aware that subtyping and inheritance are not related. Inheritance is a 1126syntactic relation between classes while subtyping is a semantic relation 1127between types. For instance, the class of colored points could have been 1128defined directly, without inheriting from the class of points; the type of 1129colored points would remain unchanged and thus still be a subtype of 1130points. 1131</p><p>The domain of a coercion can often be omitted. For instance, one can 1132define: 1133</p><div class="caml-example"> 1134<pre><div class="caml-input"> let to_point cp = (cp :> point);; 1135</div><div class="caml-output ok">val to_point : #point -> point = <fun> 1136</div></pre> 1137 1138</div><p>In this case, the function <span class="c003">colored_point_to_point</span> is an instance of the 1139function <span class="c003">to_point</span>. This is not always true, however. The fully 1140explicit coercion is more precise and is sometimes unavoidable. 1141Consider, for example, the following class: 1142</p><div class="caml-example"> 1143<pre><div class="caml-input"> class c0 = object method m = {< >} method n = 0 end;; 1144</div><div class="caml-output ok">class c0 : object ('a) method m : 'a method n : int end 1145</div></pre> 1146 1147</div><p>The object type <span class="c003">c0</span> is an abbreviation for <span class="c003"><m : 'a; n : int> as 'a</span>. 1148Consider now the type declaration: 1149</p><div class="caml-example"> 1150<pre><div class="caml-input"> class type c1 = object method m : c1 end;; 1151</div><div class="caml-output ok">class type c1 = object method m : c1 end 1152</div></pre> 1153 1154</div><p>The object type <span class="c003">c1</span> is an abbreviation for the type <span class="c003"><m : 'a> as 'a</span>. 1155The coercion from an object of type <span class="c003">c0</span> to an object of type <span class="c003">c1</span> is 1156correct: 1157</p><div class="caml-example"> 1158<pre><div class="caml-input"> fun (x:c0) -> (x : c0 :> c1);; 1159</div><div class="caml-output ok">- : c0 -> c1 = <fun> 1160</div></pre> 1161 1162</div><p>However, the domain of the coercion cannot always be omitted. 1163In that case, the solution is to use the explicit form. 1164Sometimes, a change in the class-type definition can also solve the problem 1165</p><div class="caml-example"> 1166<pre><div class="caml-input"> class type c2 = object ('a) method m : 'a end;; 1167</div><div class="caml-output ok">class type c2 = object ('a) method m : 'a end 1168</div></pre> 1169 1170<pre><div class="caml-input"> fun (x:c0) -> (x :> c2);; 1171</div><div class="caml-output ok">- : c0 -> c2 = <fun> 1172</div></pre> 1173 1174</div><p>While class types <span class="c003">c1</span> and <span class="c003">c2</span> are different, both object types 1175<span class="c003">c1</span> and <span class="c003">c2</span> expand to the same object type (same method names and types). 1176Yet, when the domain of a coercion is left implicit and its co-domain 1177is an abbreviation of a known class type, then the class type, rather 1178than the object type, is used to derive the coercion function. This 1179allows leaving the domain implicit in most cases when coercing form a 1180subclass to its superclass. 1181The type of a coercion can always be seen as below: 1182</p><div class="caml-example"> 1183<pre><div class="caml-input"> let to_c1 x = (x :> c1);; 1184</div><div class="caml-output ok">val to_c1 : < m : #c1; .. > -> c1 = <fun> 1185</div></pre> 1186 1187<pre><div class="caml-input"> let to_c2 x = (x :> c2);; 1188</div><div class="caml-output ok">val to_c2 : #c2 -> c2 = <fun> 1189</div></pre> 1190 1191</div><p>Note the difference between these two coercions: in the case of <span class="c003">to_c2</span>, 1192the type 1193<span class="c003">#c2 = < m : 'a; .. > as 'a</span> is polymorphically recursive (according 1194to the explicit recursion in the class type of <span class="c003">c2</span>); hence the 1195success of applying this coercion to an object of class <span class="c003">c0</span>. 1196On the other hand, in the first case, <span class="c003">c1</span> was only expanded and 1197unrolled twice to obtain <span class="c003">< m : < m : c1; .. >; .. ></span> (remember <span class="c003">#c1 = < m : c1; .. ></span>), without introducing recursion. 1198You may also note that the type of <span class="c003">to_c2</span> is <span class="c003">#c2 -> c2</span> while 1199the type of <span class="c003">to_c1</span> is more general than <span class="c003">#c1 -> c1</span>. This is not always true, 1200since there are class types for which some instances of <span class="c003">#c</span> are not subtypes 1201of <span class="c003">c</span>, as explained in section <a href="#ss%3Abinary-methods">3.16</a>. Yet, for 1202parameterless classes the coercion <span class="c003">(_ :> c)</span> is always more general than 1203<span class="c003">(_ : #c :> c)</span>. 1204</p><p>A common problem may occur when one tries to define a coercion to a 1205class <span class="c003">c</span> while defining class <span class="c003">c</span>. The problem is due to the type 1206abbreviation not being completely defined yet, and so its subtypes are not 1207clearly known. Then, a coercion <span class="c003">(_ :> c)</span> or <span class="c003">(_ : #c :> c)</span> is taken to be 1208the identity function, as in 1209</p><div class="caml-example"> 1210<pre><div class="caml-input"> function x -> (x :> 'a);; 1211</div><div class="caml-output ok">- : 'a -> 'a = <fun> 1212</div></pre> 1213 1214</div><p>As a consequence, if the coercion is applied to <span class="c003">self</span>, as in the 1215following example, the type of <span class="c003">self</span> is unified with the closed type 1216<span class="c003">c</span> (a closed object type is an object type without ellipsis). This 1217would constrain the type of self be closed and is thus rejected. 1218Indeed, the type of self cannot be closed: this would prevent any 1219further extension of the class. Therefore, a type error is generated 1220when the unification of this type with another type would result in a 1221closed object type. 1222</p><div class="caml-example"> 1223<pre><div class="caml-input"> class c = object method m = 1 end 1224 and d = object (self) 1225 inherit c 1226 method n = 2 1227 method as_c = (<U>self</U> :> c) 1228 end;; 1229</div><div class="caml-output error">Error: This expression cannot be coerced to type c = < m : int >; it has type 1230 < as_c : c; m : int; n : int; .. > 1231 but is here used with type c 1232 Self type cannot escape its class 1233</div></pre> 1234 1235</div><p>However, the most common instance of this problem, coercing self to 1236its current class, is detected as a special case by the type checker, 1237and properly typed. 1238</p><div class="caml-example"> 1239<pre><div class="caml-input"> class c = object (self) method m = (self :> c) end;; 1240</div><div class="caml-output ok">class c : object method m : c end 1241</div></pre> 1242 1243</div><p>This allows the following idiom, keeping a list of all objects 1244belonging to a class or its subclasses: 1245</p><div class="caml-example"> 1246<pre><div class="caml-input"> let all_c = ref [];; 1247</div><div class="caml-output ok">val all_c : '_a list ref = {contents = []} 1248</div></pre> 1249 1250<pre><div class="caml-input"> class c (m : int) = 1251 object (self) 1252 method m = m 1253 initializer all_c := (self :> c) :: !all_c 1254 end;; 1255</div><div class="caml-output ok">class c : int -> object method m : int end 1256</div></pre> 1257 1258</div><p>This idiom can in turn be used to retrieve an object whose type has 1259been weakened: 1260</p><div class="caml-example"> 1261<pre><div class="caml-input"> let rec lookup_obj obj = function [] -> raise Not_found 1262 | obj' :: l -> 1263 if (obj :> < >) = (obj' :> < >) then obj' else lookup_obj obj l ;; 1264</div><div class="caml-output ok">val lookup_obj : < .. > -> (< .. > as 'a) list -> 'a = <fun> 1265</div></pre> 1266 1267<pre><div class="caml-input"> let lookup_c obj = lookup_obj obj !all_c;; 1268</div><div class="caml-output ok">val lookup_c : < .. > -> < m : int > = <fun> 1269</div></pre> 1270 1271</div><p>The type <span class="c003">< m : int ></span> we see here is just the expansion of <span class="c003">c</span>, due 1272to the use of a reference; we have succeeded in getting back an object 1273of type <span class="c003">c</span>.</p><p><br> 1274The previous coercion problem can often be avoided by first 1275defining the abbreviation, using a class type: 1276</p><div class="caml-example"> 1277<pre><div class="caml-input"> class type c' = object method m : int end;; 1278</div><div class="caml-output ok">class type c' = object method m : int end 1279</div></pre> 1280 1281<pre><div class="caml-input"> class c : c' = object method m = 1 end 1282 and d = object (self) 1283 inherit c 1284 method n = 2 1285 method as_c = (self :> c') 1286 end;; 1287</div><div class="caml-output ok">class c : c' 1288and d : object method as_c : c' method m : int method n : int end 1289</div></pre> 1290 1291</div><p>It is also possible to use a virtual class. Inheriting from this class 1292simultaneously forces all methods of <span class="c003">c</span> to have the same 1293type as the methods of <span class="c003">c'</span>. 1294</p><div class="caml-example"> 1295<pre><div class="caml-input"> class virtual c' = object method virtual m : int end;; 1296</div><div class="caml-output ok">class virtual c' : object method virtual m : int end 1297</div></pre> 1298 1299<pre><div class="caml-input"> class c = object (self) inherit c' method m = 1 end;; 1300</div><div class="caml-output ok">class c : object method m : int end 1301</div></pre> 1302 1303</div><p>One could think of defining the type abbreviation directly: 1304</p><div class="caml-example"> 1305<pre><div class="caml-input"> type c' = <m : int>;; 1306</div> 1307</pre> 1308 1309</div><p>However, the abbreviation <span class="c003">#c'</span> cannot be defined directly in a similar way. 1310It can only be defined by a class or a class-type definition. 1311This is because a <span class="c003">#</span>-abbreviation carries an implicit anonymous 1312variable <span class="c003">..</span> that cannot be explicitly named. 1313The closer you get to it is: 1314</p><div class="caml-example"> 1315<pre><div class="caml-input"> type 'a c'_class = 'a constraint 'a = < m : int; .. >;; 1316</div> 1317</pre> 1318 1319</div><p>with an extra type variable capturing the open object type.</p> 1320<h2 class="section" id="sec36">3.13  Functional objects</h2> 1321<p> 1322 1323<a id="ss:functional-objects"></a></p><p>It is possible to write a version of class <span class="c003">point</span> without assignments 1324on the instance variables. The override construct <span class="c003">{< ... >}</span> returns a copy of 1325“self” (that is, the current object), possibly changing the value of 1326some instance variables. 1327</p><div class="caml-example"> 1328<pre><div class="caml-input"> class functional_point y = 1329 object 1330 val x = y 1331 method get_x = x 1332 method move d = {< x = x + d >} 1333 end;; 1334</div><div class="caml-output ok">class functional_point : 1335 int -> 1336 object ('a) val x : int method get_x : int method move : int -> 'a end 1337</div></pre> 1338 1339<pre><div class="caml-input"> let p = new functional_point 7;; 1340</div><div class="caml-output ok">val p : functional_point = <obj> 1341</div></pre> 1342 1343<pre><div class="caml-input"> p#get_x;; 1344</div><div class="caml-output ok">- : int = 7 1345</div></pre> 1346 1347<pre><div class="caml-input"> (p#move 3)#get_x;; 1348</div><div class="caml-output ok">- : int = 10 1349</div></pre> 1350 1351<pre><div class="caml-input"> p#get_x;; 1352</div><div class="caml-output ok">- : int = 7 1353</div></pre> 1354 1355</div><p>Note that the type abbreviation <span class="c003">functional_point</span> is recursive, which can 1356be seen in the class type of <span class="c003">functional_point</span>: the type of self is <span class="c003">'a</span> 1357and <span class="c003">'a</span> appears inside the type of the method <span class="c003">move</span>.</p><p>The above definition of <span class="c003">functional_point</span> is not equivalent 1358to the following: 1359</p><div class="caml-example"> 1360<pre><div class="caml-input"> class bad_functional_point y = 1361 object 1362 val x = y 1363 method get_x = x 1364 method move d = new bad_functional_point (x+d) 1365 end;; 1366</div><div class="caml-output ok">class bad_functional_point : 1367 int -> 1368 object 1369 val x : int 1370 method get_x : int 1371 method move : int -> bad_functional_point 1372 end 1373</div></pre> 1374 1375</div><p>While objects of either class will behave the same, objects of their 1376subclasses will be different. In a subclass of <span class="c003">bad_functional_point</span>, 1377the method <span class="c003">move</span> will 1378keep returning an object of the parent class. On the contrary, in a 1379subclass of <span class="c003">functional_point</span>, the method <span class="c003">move</span> will return an 1380object of the subclass.</p><p>Functional update is often used in conjunction with binary methods 1381as illustrated in section <a href="advexamples.html#module%3Astring">5.2.1</a>.</p> 1382<h2 class="section" id="sec37">3.14  Cloning objects</h2> 1383<p> 1384 1385<a id="ss:cloning-objects"></a></p><p>Objects can also be cloned, whether they are functional or imperative. 1386The library function <span class="c003">Oo.copy</span> makes a shallow copy of an object. That is, 1387it returns a new object that has the same methods and instance 1388variables as its argument. The 1389instance variables are copied but their contents are shared. 1390Assigning a new value to an instance variable of the copy (using a method 1391call) will not affect instance variables of the original, and conversely. 1392A deeper assignment (for example if the instance variable is a reference cell) 1393will of course affect both the original and the copy.</p><p>The type of <span class="c003">Oo.copy</span> is the following: 1394</p><div class="caml-example"> 1395<pre><div class="caml-input"> Oo.copy;; 1396</div><div class="caml-output ok">- : (< .. > as 'a) -> 'a = <fun> 1397</div></pre> 1398 1399</div><p>The keyword <span class="c003">as</span> in that type binds the type variable <span class="c003">'a</span> to 1400the object type <span class="c003">< .. ></span>. Therefore, <span class="c003">Oo.copy</span> takes an object with 1401any methods (represented by the ellipsis), and returns an object of 1402the same type. The type of <span class="c003">Oo.copy</span> is different from type <span class="c003">< .. > -> < .. ></span> as each ellipsis represents a different set of methods. 1403Ellipsis actually behaves as a type variable. 1404</p><div class="caml-example"> 1405<pre><div class="caml-input"> let p = new point 5;; 1406</div><div class="caml-output ok">val p : point = <obj> 1407</div></pre> 1408 1409<pre><div class="caml-input"> let q = Oo.copy p;; 1410</div><div class="caml-output ok">val q : point = <obj> 1411</div></pre> 1412 1413<pre><div class="caml-input"> q#move 7; (p#get_x, q#get_x);; 1414</div><div class="caml-output ok">- : int * int = (5, 12) 1415</div></pre> 1416 1417</div><p>In fact, <span class="c003">Oo.copy p</span> will behave as <span class="c003">p#copy</span> assuming that a public 1418method <span class="c003">copy</span> with body <span class="c003">{< >}</span> has been defined in the class of <span class="c003">p</span>.</p><p>Objects can be compared using the generic comparison functions <span class="c003">=</span> and <span class="c003"><></span>. 1419Two objects are equal if and only if they are physically equal. In 1420particular, an object and its copy are not equal. 1421</p><div class="caml-example"> 1422<pre><div class="caml-input"> let q = Oo.copy p;; 1423</div><div class="caml-output ok">val q : point = <obj> 1424</div></pre> 1425 1426<pre><div class="caml-input"> p = q, p = p;; 1427</div><div class="caml-output ok">- : bool * bool = (false, true) 1428</div></pre> 1429 1430</div><p>Other generic comparisons such as (<span class="c003"><</span>, <span class="c003"><=</span>, ...) can also be used on 1431objects. The 1432relation <span class="c003"><</span> defines an unspecified but strict ordering on objects. The 1433ordering relationship between two objects is fixed once for all after the 1434two objects have been created and it is not affected by mutation of fields.</p><p>Cloning and override have a non empty intersection. 1435They are interchangeable when used within an object and without 1436overriding any field: 1437</p><div class="caml-example"> 1438<pre><div class="caml-input"> class copy = 1439 object 1440 method copy = {< >} 1441 end;; 1442</div><div class="caml-output ok">class copy : object ('a) method copy : 'a end 1443</div></pre> 1444 1445<pre><div class="caml-input"> class copy = 1446 object (self) 1447 method copy = Oo.copy self 1448 end;; 1449</div><div class="caml-output ok">class copy : object ('a) method copy : 'a end 1450</div></pre> 1451 1452</div><p>Only the override can be used to actually override fields, and 1453only the <span class="c003">Oo.copy</span> primitive can be used externally.</p><p>Cloning can also be used to provide facilities for saving and 1454restoring the state of objects. 1455</p><div class="caml-example"> 1456<pre><div class="caml-input"> class backup = 1457 object (self : 'mytype) 1458 val mutable copy = None 1459 method save = copy <- Some {< copy = None >} 1460 method restore = match copy with Some x -> x | None -> self 1461 end;; 1462</div><div class="caml-output ok">class backup : 1463 object ('a) 1464 val mutable copy : 'a option 1465 method restore : 'a 1466 method save : unit 1467 end 1468</div></pre> 1469 1470</div><p>The above definition will only backup one level. 1471The backup facility can be added to any class by using multiple inheritance. 1472</p><div class="caml-example"> 1473<pre><div class="caml-input"> class ['a] backup_ref x = object inherit ['a] oref x inherit backup end;; 1474</div><div class="caml-output ok">class ['a] backup_ref : 1475 'a -> 1476 object ('b) 1477 val mutable copy : 'b option 1478 val mutable x : 'a 1479 method get : 'a 1480 method restore : 'b 1481 method save : unit 1482 method set : 'a -> unit 1483 end 1484</div></pre> 1485 1486<pre><div class="caml-input"> let rec get p n = if n = 0 then p # get else get (p # restore) (n-1);; 1487</div><div class="caml-output ok">val get : (< get : 'b; restore : 'a; .. > as 'a) -> int -> 'b = <fun> 1488</div></pre> 1489 1490<pre><div class="caml-input"> let p = new backup_ref 0 in 1491 p # save; p # set 1; p # save; p # set 2; 1492 [get p 0; get p 1; get p 2; get p 3; get p 4];; 1493</div><div class="caml-output ok">- : int list = [2; 1; 1; 1; 1] 1494</div></pre> 1495 1496</div><p>We can define a variant of backup that retains all copies. (We also 1497add a method <span class="c003">clear</span> to manually erase all copies.) 1498</p><div class="caml-example"> 1499<pre><div class="caml-input"> class backup = 1500 object (self : 'mytype) 1501 val mutable copy = None 1502 method save = copy <- Some {< >} 1503 method restore = match copy with Some x -> x | None -> self 1504 method clear = copy <- None 1505 end;; 1506</div><div class="caml-output ok">class backup : 1507 object ('a) 1508 val mutable copy : 'a option 1509 method clear : unit 1510 method restore : 'a 1511 method save : unit 1512 end 1513</div></pre> 1514 1515</div><div class="caml-example"> 1516<pre><div class="caml-input"> class ['a] backup_ref x = object inherit ['a] oref x inherit backup end;; 1517</div><div class="caml-output ok">class ['a] backup_ref : 1518 'a -> 1519 object ('b) 1520 val mutable copy : 'b option 1521 val mutable x : 'a 1522 method clear : unit 1523 method get : 'a 1524 method restore : 'b 1525 method save : unit 1526 method set : 'a -> unit 1527 end 1528</div></pre> 1529 1530<pre><div class="caml-input"> let p = new backup_ref 0 in 1531 p # save; p # set 1; p # save; p # set 2; 1532 [get p 0; get p 1; get p 2; get p 3; get p 4];; 1533</div><div class="caml-output ok">- : int list = [2; 1; 0; 0; 0] 1534</div></pre> 1535 1536</div> 1537<h2 class="section" id="sec38">3.15  Recursive classes</h2> 1538<p> 1539 1540<a id="ss:recursive-classes"></a></p><p>Recursive classes can be used to define objects whose types are 1541mutually recursive. 1542</p><div class="caml-example"> 1543<pre><div class="caml-input"> class window = 1544 object 1545 val mutable top_widget = (None : widget option) 1546 method top_widget = top_widget 1547 end 1548 and widget (w : window) = 1549 object 1550 val window = w 1551 method window = window 1552 end;; 1553</div><div class="caml-output ok">class window : 1554 object 1555 val mutable top_widget : widget option 1556 method top_widget : widget option 1557 end 1558and widget : window -> object val window : window method window : window end 1559</div></pre> 1560 1561</div><p>Although their types are mutually recursive, the classes <span class="c003">widget</span> and 1562<span class="c003">window</span> are themselves independent.</p> 1563<h2 class="section" id="sec39">3.16  Binary methods</h2> 1564<p> 1565 1566<a id="ss:binary-methods"></a></p><p>A binary method is a method which takes an argument of the same type 1567as self. The class <span class="c003">comparable</span> below is a template for classes with a 1568binary method <span class="c003">leq</span> of type <span class="c003">'a -> bool</span> where the type variable <span class="c003">'a</span> 1569is bound to the type of self. Therefore, <span class="c003">#comparable</span> expands to <span class="c003">< leq : 'a -> bool; .. > as 'a</span>. We see here that the binder <span class="c003">as</span> also 1570allows writing recursive types. 1571</p><div class="caml-example"> 1572<pre><div class="caml-input"> class virtual comparable = 1573 object (_ : 'a) 1574 method virtual leq : 'a -> bool 1575 end;; 1576</div><div class="caml-output ok">class virtual comparable : object ('a) method virtual leq : 'a -> bool end 1577</div></pre> 1578 1579</div><p>We then define a subclass <span class="c003">money</span> of <span class="c003">comparable</span>. The class <span class="c003">money</span> 1580simply wraps floats as comparable objects. We will extend it below with 1581more operations. We have to use a type constraint on the class parameter <span class="c003">x</span> 1582because the primitive <span class="c003"><=</span> is a polymorphic function in 1583OCaml. The <span class="c003">inherit</span> clause ensures that the type of objects 1584of this class is an instance of <span class="c003">#comparable</span>. 1585</p><div class="caml-example"> 1586<pre><div class="caml-input"> class money (x : float) = 1587 object 1588 inherit comparable 1589 val repr = x 1590 method value = repr 1591 method leq p = repr <= p#value 1592 end;; 1593</div><div class="caml-output ok">class money : 1594 float -> 1595 object ('a) 1596 val repr : float 1597 method leq : 'a -> bool 1598 method value : float 1599 end 1600</div></pre> 1601 1602</div><p>Note that the type <span class="c003">money</span> is not a subtype of type 1603<span class="c003">comparable</span>, as the self type appears in contravariant position 1604in the type of method <span class="c003">leq</span>. 1605Indeed, an object <span class="c003">m</span> of class <span class="c003">money</span> has a method <span class="c003">leq</span> 1606that expects an argument of type <span class="c003">money</span> since it accesses 1607its <span class="c003">value</span> method. Considering <span class="c003">m</span> of type <span class="c003">comparable</span> would allow a 1608call to method <span class="c003">leq</span> on <span class="c003">m</span> with an argument that does not have a method 1609<span class="c003">value</span>, which would be an error.</p><p>Similarly, the type <span class="c003">money2</span> below is not a subtype of type <span class="c003">money</span>. 1610</p><div class="caml-example"> 1611<pre><div class="caml-input"> class money2 x = 1612 object 1613 inherit money x 1614 method times k = {< repr = k *. repr >} 1615 end;; 1616</div><div class="caml-output ok">class money2 : 1617 float -> 1618 object ('a) 1619 val repr : float 1620 method leq : 'a -> bool 1621 method times : float -> 'a 1622 method value : float 1623 end 1624</div></pre> 1625 1626</div><p>It is however possible to define functions that manipulate objects of 1627type either <span class="c003">money</span> or <span class="c003">money2</span>: the function <span class="c003">min</span> 1628will return the minimum of any two objects whose type unifies with 1629<span class="c003">#comparable</span>. The type of <span class="c003">min</span> is not the same as <span class="c003">#comparable -> #comparable -> #comparable</span>, as the abbreviation <span class="c003">#comparable</span> hides a 1630type variable (an ellipsis). Each occurrence of this abbreviation 1631generates a new variable. 1632</p><div class="caml-example"> 1633<pre><div class="caml-input"> let min (x : #comparable) y = 1634 if x#leq y then x else y;; 1635</div><div class="caml-output ok">val min : (#comparable as 'a) -> 'a -> 'a = <fun> 1636</div></pre> 1637 1638</div><p>This function can be applied to objects of type <span class="c003">money</span> 1639or <span class="c003">money2</span>. 1640</p><div class="caml-example"> 1641<pre><div class="caml-input"> (min (new money 1.3) (new money 3.1))#value;; 1642</div><div class="caml-output ok">- : float = 1.3 1643</div></pre> 1644 1645<pre><div class="caml-input"> (min (new money2 5.0) (new money2 3.14))#value;; 1646</div><div class="caml-output ok">- : float = 3.14 1647</div></pre> 1648 1649</div><p>More examples of binary methods can be found in sections 1650<a href="advexamples.html#module%3Astring">5.2.1</a> and <a href="advexamples.html#module%3Aset">5.2.3</a>.</p><p>Note the use of override for method <span class="c003">times</span>. 1651Writing <span class="c003">new money2 (k *. repr)</span> instead of <span class="c003">{< repr = k *. repr >}</span> 1652would not behave well with inheritance: in a subclass <span class="c003">money3</span> of <span class="c003">money2</span> 1653the <span class="c003">times</span> method would return an object of class <span class="c003">money2</span> but not of class 1654<span class="c003">money3</span> as would be expected.</p><p>The class <span class="c003">money</span> could naturally carry another binary method. Here is a 1655direct definition: 1656</p><div class="caml-example"> 1657<pre><div class="caml-input"> class money x = 1658 object (self : 'a) 1659 val repr = x 1660 method value = repr 1661 method print = print_float repr 1662 method times k = {< repr = k *. x >} 1663 method leq (p : 'a) = repr <= p#value 1664 method plus (p : 'a) = {< repr = x +. p#value >} 1665 end;; 1666</div><div class="caml-output ok">class money : 1667 float -> 1668 object ('a) 1669 val repr : float 1670 method leq : 'a -> bool 1671 method plus : 'a -> 'a 1672 method print : unit 1673 method times : float -> 'a 1674 method value : float 1675 end 1676</div></pre> 1677 1678</div> 1679<h2 class="section" id="sec40">3.17  Friends</h2> 1680<p> 1681 1682<a id="ss:friends"></a></p><p>The above class <span class="c003">money</span> reveals a problem that often occurs with binary 1683methods. In order to interact with other objects of the same class, the 1684representation of <span class="c003">money</span> objects must be revealed, using a method such as 1685<span class="c003">value</span>. If we remove all binary methods (here <span class="c003">plus</span> and <span class="c003">leq</span>), 1686the representation can easily be hidden inside objects by removing the method 1687<span class="c003">value</span> as well. However, this is not possible as soon as some binary 1688method requires access to the representation of objects of the same 1689class (other than self). 1690</p><div class="caml-example"> 1691<pre><div class="caml-input"> class safe_money x = 1692 object (self : 'a) 1693 val repr = x 1694 method print = print_float repr 1695 method times k = {< repr = k *. x >} 1696 end;; 1697</div><div class="caml-output ok">class safe_money : 1698 float -> 1699 object ('a) 1700 val repr : float 1701 method print : unit 1702 method times : float -> 'a 1703 end 1704</div></pre> 1705 1706</div><p>Here, the representation of the object is known only to a particular object. 1707To make it available to other objects of the same class, we are forced to 1708make it available to the whole world. However we can easily restrict the 1709visibility of the representation using the module system. 1710</p><div class="caml-example"> 1711<pre><div class="caml-input"> module type MONEY = 1712 sig 1713 type t 1714 class c : float -> 1715 object ('a) 1716 val repr : t 1717 method value : t 1718 method print : unit 1719 method times : float -> 'a 1720 method leq : 'a -> bool 1721 method plus : 'a -> 'a 1722 end 1723 end;; 1724</div> 1725</pre> 1726 1727<pre><div class="caml-input"> module Euro : MONEY = 1728 struct 1729 type t = float 1730 class c x = 1731 object (self : 'a) 1732 val repr = x 1733 method value = repr 1734 method print = print_float repr 1735 method times k = {< repr = k *. x >} 1736 method leq (p : 'a) = repr <= p#value 1737 method plus (p : 'a) = {< repr = x +. p#value >} 1738 end 1739 end;; 1740</div> 1741</pre> 1742 1743</div><p>Another example of friend functions may be found in section 1744<a href="advexamples.html#module%3Aset">5.2.3</a>. These examples occur when a group of objects (here 1745objects of the same class) and functions should see each others internal 1746representation, while their representation should be hidden from the 1747outside. The solution is always to define all friends in the same module, 1748give access to the representation and use a signature constraint to make the 1749representation abstract outside the module.</p> 1750<hr> 1751<a href="moduleexamples.html"><img src="previous_motif.gif" alt="Previous"></a> 1752<a href="index.html"><img src="contents_motif.gif" alt="Up"></a> 1753<a href="lablexamples.html"><img src="next_motif.gif" alt="Next"></a> 1754</body> 1755</html> 1756