👑

Nimでclass構文が使えるパッケージをつくった

commits2 min read

はじめに

こんにちは、Neoと申します。
タイトルの通り、Nimでclass構文が使えるパッケージをつくったので、紹介します。

つくったもの

「OOlib(おーおーりぶ)」といいます。

https://github.com/Glasses-Neo/OOlib

install

nimble install oolib
  • 継承(objectのみ)
  • distinct
  • コンストラクターの自動定義
  • self, superキーワード

などの機能があります。
簡単に使い方を説明します。

使い方

class

基本的には、他の言語のclassと同じように使えます。

class Person:
  var name: string
  var age: int = 0

proc happyBirthday() =
  inc self.age

let
  p1 = newPerson("Sam")
  p2 = newPerson("Steve", "100")

変数

メンバー変数はグローバル変数と同じくvarで定義し、ネストや複数を同時に定義、デフォルト値の設定などができます。

class A:
  var a: int # 通常
  var
    b: string # ネスト
  var c, d: bool = true # 複数同時定義、デフォルト値あり

プロシージャ

プロシージャ系は、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}!!!"

公開

class pub クラス名でそのクラスを公開できます。
メンバー変数、プロシージャなどは通常と同じ方法でできます。
コンストラクターは、クラス自体の公開/非公開を自動で反映します。

class pub A:
  var a*, b: int

  # クラスが公開されているので自動で公開される
  proc `new`(str: string) =
    self.a = str.len
    self.b = str.len

  proc inc* =
    inc a
    inc b

おわりに

現在検討している機能は、オブジェクト以外の継承、TypeScriptのPickに相当するマクロなどです。
最後までお読みいただきありがとうございました。リポジトリにstarしていただけると嬉しいです。

GitHubで編集を提案

Discussion

ログインするとコメントできます