# Log - Moonshile

## 2014-12-05

Published on 2014-12-05

## OCaml Object-Oriented Features

### Basics

Note that the relation between object, class and type in OCaml is very different from that in mainstream object-oriented languages like Java or C++, so that you should not assume that similar keywords mean the same thing.

class point =
object
val mutable x = 0
method get_x = x
method move d = x <- x + d
end;;

let p = new point;;
p#get_x;; (* 0 *)
p#move 3;;
p#get_x;; (* 3 *)

Class could have parameters, which are visible in the whole body of the definition, including methods.

class point x_init =
object
val mutable x = x_init
method get_x = x
method get_offset = x - x_init
method move d = x <- x + d
end;;

new point;; (* this is a function of type int -> point *)
let p = new point 7;; (* this is an object *)

Expressions can be evaluated and bound before defining the object body of the class.

class adjusted_point x_init =
let origin = (x_init / 10) * 10 in
object
val mutable x = origin
method get_x = x
method get_offset = x - origin
method move d = x <- x + d
end;;

### Immediate Objects

There is another, more direct way to create an object: create it without going through a class. Unlike classes, which cannot be defined inside an expression, immediate objects can appear anywhere, using variables from their environment. Immediate objects have two weaknesses compared to classes: their types are not abbreviated, and you cannot inherit from them. But these two weaknesses can be advantages in some situations.

let p =
object
val mutable x = 0
method get_x = x
method move d = x <- x + d
end;;

p#get_x;; (* 0 *)
p#move 3;;
p#get_x;; (* 3 *)

### Reference to Self

A method or an initializer can send messages to self (that is, the current object). For that, self must be explicitly bound, here to the variable s (s could be any identifier, even though we will often choose the name self.)

class printable_point x_init =
object (s)
val mutable x = x_init
method get_x = x
method move d = x <- x + d
method print = print_int s#get_x;print_newline()
end;;

let p = new printable_point 7;;
p#print;;

### Initializers

Let-bindings within class definitions are evaluated before the object is constructed. It is also possible to evaluate an expression immediately after the object has been built. Such code is written as an anonymous hidden method called an initializer. Therefore, it can access self and the instance variables.

class printable_point x_init =
let origin = (x_init / 10) * 10 in
object (self)
val mutable x = origin
method get_x = x
method move d = x <- x + d
method print = print_int self#get_x
initializer print_string "new point at "; self#print; print_newline ()
end;;

let p = new printable_point 17;; (* the initializer will be evaluated immediately, with some messages printed out *)