-
Notifications
You must be signed in to change notification settings - Fork 4
Documentation
import oolib
# create Person type
class Person:
var
name*: string
age* = 0
let
tony = Person.new("Tony")
steve = Person.new("Steve", 100)
doAssert tony.name == "Tony"
doAssert tony.age == 0
doAssert steve.name == "Steve"
doAssert steve.age == 100
pub
is instead of *
.
example:
# `A` is exported
class pub A
# `B` is not exported
class B
class
can define member variables starting with var
and they can be set to default values.
class A:
var a: int
var b: string
class B:
# infer types from default values
var
c = "default"
d = 1.5
Data constants are constants that can be accessed from both a type and an instance.
they start with const
and their value must be set when a class is defined.
class MoneySymbol:
const JPY = "¥"
const US = "$"
class
defines constructor automatically from definition of member variables in its body. Once a class is exported, a constructor is also exported.
example:
class Sword:
var offence: int
proc attack() =
echo "attack!"
# `Sword.new` is automatically defined.
let sword = Sword.new(9)
When a variable has a default value, an argument of constructor has a default value just like it.
class List:
items: seq[string] = @[]
var
list1 = List.new(@["apple", "orange"])
list2 = List.new()
class
auto-inserts followings:
- return type
- member variables with default values as arguments of constructor
-
var self: Type
in the 1st line of constructor -
return self
in the last line of constructor
class Gun:
var
capacity: uint
bullets: uint
proc `new`(capacity: uint) =
self.capacity = capacity
self.bullets = capacity
proc shoot() =
if self.bullets > 0:
self.bullets = self.bullets - 1
else:
echo "Out of bullets!"
let gun = Gun.new(6)
Mark with {.noNewDef.} not to define constructor.
class Data {.noNewDef.}:
var x, y: int
discard Data.new(1, 2) # error!
class
supports proc
, func
, method
, iterator
, converter
, and template
, with the only exception being macro
.
For these, self
is automatically inserted as the first argument.
class
can omit its body.
class A:
discard
# is same as
class B
Generic types are supported only in normal classes for now and cannot be used in member variables.
class A[T]:
proc f1[T](s: seq[T]) =
for i in s:
echo i
let a1 = A[int].new()
let a2 = A[string].new()
a1.f1 @[4, 2, 4]
a2.f1 @["a", "b"]
Inheritance is done as follows:
# Mark {.open.} to be inheritable
class A {.open.}
class B of A
# This will be parsed as Alias
class B(A)
# This is not inheritable
class C
# error!
class D of C
Superclass must be marked with {.open.}
.
In methods of class, super
keyword is defined to access superclass.
from typetraits import name
class A {.open.}:
method abstractMethod {.base.} =
echo &"Abstract method of {self.type.name}!!!"
class B of A:
method concreteMethod =
super.abstractMethod()
echo &"Concrete method of {self.type.name}!!!"
example:
class Dollar(distinct int):
proc `+`(v: Dollar): Dollar {.borrow.}
proc `$`: string {.borrow.}
echo 100.Dollar + 50.Dollar
example:
# It's same as `type A = int`
class A(int)
class can implement protocol
, described later.
It returns whether a type is class or not. example:
class A
let a = A()
# Both are available
assert A.isClass()
assert a.isClass()
protocol
provides tuple for interface. For now, multiple implementation is not supported.
protocol Animal:
var scientificName: string
proc breathe()
proc roar()
class Cat impl Animal:
var scientificName: string
var name {.ignored.}: string
proc breathe() =
echo "breathed!"
proc roar() =
echo "meow!"
class Dog impl Animal:
var scientificName: string
var name {.ignored.}: string
proc breathe() =
echo "breathed!"
proc roar() =
echo "bark!"
let cat = Cat.new("Felis catus", "Leo").toInterface()
let dog = Dog.new("Canis lupus familiaris", "Wolf").toInterface()
cat.breathe()
cat.roar()
dog.breathe()
dog.roar()
pub
is instead of *
.
protocol
can define member variables starting with var
and they cannot be set to default values.
protocol
can force class
to implement procedures.
protocol Walkable:
proc walk()
class Person impl Walkable:
proc walk() = echo "Walking!"
# error!
class Robot impl Walkable:
proc run() = echo "Running!"
Mark with {.ignored.}
to ignore properties that isn't defined in protocol
.
protocol SNS:
var username: string
class Discard impl SNS:
var username: string
var mail {.ignored.}: string
var password {.ignored.}: string
proc verify() {.ignored.} =
discard
a class that implements a protocol has toInterface()
to be converted to interface.
protocol Weapon:
var offence: int
class Sword impl Weapon:
var offence: int
class Hatchet impl Weapon:
var offence: int
class Player:
var equipment: Weapon
let sword = Sword.new(5).toInterface()
let hatchet = Hatchet.new(4).toInterface()
let player1 = Player.new(sword)
let player2 = Player.new(hatchet)
It returns whether a type is protocol or not. example:
protocol A:
var val1: int
let a: A = (val1: 1)
# Both are available
assert A.isProtocol()
assert a.isProtocol()