EMZETT.
Login

Kurz: object ist ein Werttyp (wie struct), ref object ein Referenztyp:

Teil des Kurses Nim

Kapitel 4 von 8 im Kurs Nim. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Objekte

object ist ein Werttyp (wie struct), ref object ein Referenztyp:

type
  Person = object
    name: string
    alter: int
 
  Konto = ref object
    inhaber: string
    stand: float
 
proc vorstellen(p: Person): string =
  p.name & " (" & $p.alter & ")"
 
proc einzahlen(k: Konto, betrag: float) =
  k.stand += betrag
 
var p = Person(name: "Mia", alter: 17)
let q = p                       # Kopie
p.alter = 18
echo vorstellen(p), " ", vorstellen(q)
echo p.vorstellen
 
let k = Konto(inhaber: "Mia", stand: 10.0)
let k2 = k                      # gleiche Referenz
k.einzahlen(5.5)
echo k2.stand
echo p
echo k[]

Ausgabe:

Mia (18) Mia (17)
Mia (18)
15.5
(name: "Mia", alter: 18)
(inhaber: "Mia", stand: 15.5)

Vererbung und Methoden

type
  Tier = ref object of RootObj
    name: string
  Hund = ref object of Tier
  Katze = ref object of Tier
 
method laut(t: Tier): string {.base.} = "..."
method laut(h: Hund): string = "Wau"
method laut(k: Katze): string = "Miau"
 
proc vorstellen(t: Tier): string = t.name & " sagt " & t.laut
 
let tiere: seq[Tier] = @[Hund(name: "Rex"), Katze(name: "Mimi"), Tier(name: "Fisch")]
for t in tiere:
  echo vorstellen(t)
echo tiere[0] of Hund, " ", tiere[1] of Hund

Ausgabe:

Rex sagt Wau
Mimi sagt Miau
Fisch sagt ...
true false

Varianten (Object Variants)

type
  FormArt = enum Kreis, Rechteck
  Form = object
    case art: FormArt
    of Kreis: radius: float
    of Rechteck:
      breite, hoehe: float
 
proc flaeche(f: Form): float =
  case f.art
  of Kreis: 3.14159 * f.radius * f.radius
  of Rechteck: f.breite * f.hoehe
 
let formen = [Form(art: Kreis, radius: 2.0), Form(art: Rechteck, breite: 3.0, hoehe: 4.0)]
for f in formen:
  echo f.art, ": ", f.flaeche

Ausgabe:

Kreis: 12.56636
Rechteck: 12.0

Generics

type
  Kiste[T] = object
    inhalt: T
 
  Stapel[T] = object
    daten: seq[T]
 
proc einpacken[T](x: T): Kiste[T] = Kiste[T](inhalt: x)
 
proc push[T](s: var Stapel[T], x: T) = s.daten.add(x)
proc pop[T](s: var Stapel[T]): T = s.daten.pop()
proc leer[T](s: Stapel[T]): bool = s.daten.len == 0
 
proc groesster[T](l: openArray[T]): T =
  result = l[0]
  for x in l:
    if x > result: result = x
 
echo einpacken(42)
echo einpacken("Text")
var s: Stapel[int]
for i in 1..4: s.push(i * i)
while not s.leer:
  stdout.write s.pop(), " "
echo ""
echo groesster([3, 9, 4])
echo groesster(["b", "z", "a"])
echo groesster([1.5, 0.5])

Ausgabe:

(inhalt: 42)
(inhalt: "Text")
16 9 4 1
9
z
1.5

Merke

  • object (Wert), ref object (Referenz) und object of RootObj für Vererbung
  • method ermöglicht dynamischen Aufruf; proc wird statisch aufgelöst
  • Object Variants (case art: FormArt) modellieren Summentypen
  • Generics ([T]) schreiben Typen und Prozeduren einmal für viele Typen

Übungsaufgabe

Schreibe einen generischen Paar[A, B]-Typ mit einer Funktion tauschen.

Quiz zur Selbstkontrolle

bei proc einpacken[T]?

  • Ein Typparameter (Generics) (richtig)
  • Ein Array
  • Ein Pragma
  • Ein Tupel

Weiter im Kurs

Zurück: Sequenzen, Tabellen, Mengen und Tupel

Weiter: Strings, Dateien und Datenformate

Alle Kapitel: Nim im Überblick