Objects and Object Variants

11.1 Object Types

Objects have value semantics (copied on assignment) and are allocated on the stack unless wrapped in ref.

type
  Point* = object
    x*, y*: float           # exported fields
  Person = object
    name: string
    age: int = 18           # default field values (Nim 2)

var p = Point(x: 1.0, y: 2.0)   # object constructor
p.x = 5.0
let q = Person(name: "Ana")     # age = 18
echo p, " ", q

11.2 Procedures on Objects ("Methods" via UFCS)

proc distance(a, b: Point): float =
  import std/math
  sqrt((a.x - b.x)^2 + (a.y - b.y)^2)

proc move(p: var Point, dx, dy: float) =
  p.x += dx; p.y += dy

var pt = Point(x: 0, y: 0)
pt.move(3, 4)
echo pt.distance(Point())

11.3 Object Variants (Tagged Unions / Sum Types)

Accessing the wrong branch raises FieldDefect at runtime.

Classic use: AST nodes, JSON values, tokens.

type
  ShapeKind = enum skCircle, skRect, skTriangle
  Shape = object
    case kind: ShapeKind
    of skCircle:
      radius: float
    of skRect:
      w, h: float
    of skTriangle:
      a, b, c: float

proc area(s: Shape): float =
  case s.kind
  of skCircle: 3.14159 * s.radius * s.radius
  of skRect: s.w * s.h
  of skTriangle:
    let p = (s.a + s.b + s.c) / 2
    import std/math
    sqrt(p * (p - s.a) * (p - s.b) * (p - s.c))

echo area(Shape(kind: skCircle, radius: 2))

11.4 Equality, $, and Hashing for Objects

import std/hashes
proc hash(p: Point): Hash = hash((p.x, p.y))
# `==` and `$` are auto-generated for objects; override when needed