Nimでclass構文が使えるパッケージをつくった
はじめに
こんにちは、Neoと申します。
オブジェクト指向プログラミングのためのNimbleパッケージをつくったので、紹介します。
つくったもの
「OOlib(おーおーりぶ)」といいます。
install
nimble install oolib
使い方
class
基本的には、他の言語のclassと同じように使えます。
class Person:
var name: string
var age: int = 0
proc happyBirthday() =
inc self.age
let
p1 = Person.new("Sam")
p2 = Person.new("Steve", "100")
公開
pub
でそのクラスを公開できます。
メンバー変数、プロシージャなどは通常と同じく*
です。
class pub A:
var a*, b: int
proc inc* =
inc a
inc b
変数
メンバー変数はvar
で定義し、デフォルト値の設定ができます。
class A:
var a: int
var b: string
var c, d = true # 型推論が可能
データ定数
データ定数は、型とインスタンスの両方からアクセスできる定数です。const
で始まり、値はクラスの定義時に決定される必要があります。
class MoneySymbol:
const JPY = "¥"
const US = "$"
コンストラクタ
コンストラクタは、クラス内の変数定義をもとに自動で定義されます。コンストラクタには、クラスの公開/非公開が自動で反映されます。
class Sword:
var offence: int
proc attack() =
echo "attack!"
# `Sword.new`が自動で定義された
let sword = Sword.new(9)
プロシージャ
プロシージャ系は、proc
, func
, method
, iterator
, converter
, template
などmacro
以外のすべてに対応しています。また、自動で第1引数にそのクラスの型でself
が追加されます。(VScodeでちゃんと補完も効く)
class A:
var
name: string
age: int = 0
proc happyBirthday =
inc self.age
func addAge(x: int): int =
result = self.age + x
コンストラクター
コンストラクターは自動定義と自前で定義する方法の2種類があります。
デフォルト値を設定せず、かつ自前で定義した場合は、pythonの__init__
とよく似た挙動になります。
デフォルト値を設定し、かつ自前で定義した場合は、デフォルト値が設定されているメンバー変数だけコンストラクターの引数として挿入されます。
class A:
var
a: int
b: string
class B:
var
a: int
b: string
proc `new`(str: string) =
self.a = str.len
self.b = str
class C:
var
a: int
b: string = "default"
class D:
var
a: int
b: string = "default"
proc `new`() =
# `b: string = "default"`が引数として自動で挿入される
self.a = b.len
let
a = newA(1, "str")
b = newB("string")
c1 = newC(2, "str")
c2 = newC(3)
d1 = newD(4, "str")
d2 = newD(5)
継承
class サブクラス of スーパークラス
で継承ができます。継承するためには、スーパークラスに{.open.}
プラグマを付けなければいけません。
method
内には、スーパークラスにアクセスするためのsuper
が定義されます。また、super.メソッド()
とアクセスしてもクラッシュを起こさないようになっています。
class A {.open.}:
var name: string
proc `$`*: string = self.name
method abstractMethod {.base.} =
echo &"Abstract method of {self.name}!!!"
class B of A:
# 実装の関係で、サブクラスはコンストラクタの自動定義が不可
proc `new` =
self.name = name
method concreteMethod =
super.abstractMethod()
echo &"Concrete method of {self.name}!!!"
おわりに
現在検討している機能は、オブジェクト以外の継承、TypeScriptのPick
に相当するマクロなどです。
最後までお読みいただきありがとうございました。リポジトリにstarしていただけると嬉しいです。
Discussion