Objects & Classes

OCaml's object system is structural: an object's type is the set of its methods.

OCaml's object system is structural: an object's type is the set of its methods.

31.1 Immediate objects

let point = object
  val mutable x = 0
  method get_x = x
  method move dx = x <- x + dx
end
(* val point : < get_x : int; move : int -> unit > *)

let () = point#move 5; print_int point#get_x

31.2 Row polymorphism

.. is a row variable: "and possibly other methods".

let get_name obj = obj#name
(* val get_name : < name : 'a; .. > -> 'a   — works on ANY object with a name method *)

31.3 Classes

class counter ?(start = 0) () = object (self)
  val mutable count = start
  method get = count
  method incr = count <- count + 1; self
  method reset = count <- 0
end

let c = new counter ~start:10 ()
let _ = c#incr#incr#get       (* 12 *)

31.4 Inheritance, overriding, super

method virtual → abstract; class must be virtual.

method! / val! / inherit! → explicit override (silences warnings).

method private → callable only through self.

initializer → code run on construction.

class virtual shape name = object (self)
  method name : string = name
  method virtual area : float
  method describe = Printf.sprintf "%s with area %.2f" name self#area
end

class circle r = object (self)
  inherit shape "circle" as super
  method area = Float.pi *. r *. r
  method! describe = super#describe ^ " (r=" ^ string_of_float r ^ ")"
end

31.5 Coercion and subtyping

Subtyping is never implicit; use :>.

let shapes : shape list = [ (new circle 1.0 :> shape) ]

31.6 Class types & parameterized classes

class type printable = object method print : unit end
class ['a] stack = object
  val mutable items : 'a list = []
  method push x = items <- x :: items
  method pop = match items with [] -> None | x :: r -> items <- r; Some x
end

31.7 Functional objects {< >}

class fpoint x0 = object
  val x = x0
  method x = x
  method move d = {< x = x + d >}    (* returns a new copy *)
end

31.8 When to use objects

Rarely in idiomatic OCaml — modules + records + variants usually suffice. Objects shine for: open recursion, GUI toolkits (lablgtk), JS interop (js_of_ocaml), heterogeneous collections via structural types.