Home English

Kuina-chan

くいなちゃんDec 15, 2017


プログラミング言語Kuin」のクラスについてです。

Kuinのクラス

Kuinでは、クラスをクラス定義のように定義します。
クラス定義

 class 名前()
     メンバ定義
 end class

 class 名前(継承元クラス名)
     メンバ定義
 end class

括弧内にクラス名を書くと、そのクラスを継承したクラスになります。 省略すると「kuin@Class」を継承します。 従って、すべてのクラスは継承元を辿ると最終的に「kuin@Class」を継承していることになります。
メンバ定義には、alias文、const文、var文、classブロック、enumブロック、funcブロックが書けます。
このうち、var文はクラスのプロパティ(メンバ変数)となり、funcブロックはメソッド(メンバ関数)となります。 それ以外はクラス内でのみ参照できる定義となります。
クラスの仕様はクラスの仕様の通りです。
  • クラスを継承すると、継承元クラスのメンバがすべて引き継がれる。 継承元クラスが継承していた場合、継承元を辿ってメンバがすべて引き継がれる。
  • メンバのうちプロパティとメソッドに限って、定義の先頭に「+」を付けることで「パブリックメンバ」となり外部に公開される。 パブリックメンバ以外は外部から参照できない。
  • メソッド内では、自身のインスタンスが「me」という変数で参照できる。
クラスの仕様

継承

メソッドは、定義の先頭に「*」を付けることで、継承元クラスの同名メソッドを継承して上書きできます。
また定義の先頭に「**」を付けると、「*」と同様に同名メソッドを継承しますが、上書き後の処理を実行する前に継承元メソッドの処理を実行するようになり、つまり上書きではなく追加のような動作になります。
継承の仕様は継承の仕様の通りです。
  • 継承したメソッドは継承元のメソッドと、「+」の有無や、引数の型および名前や、戻り値の定義が一致していなければならない。
  • 「+」と「*」を両方指定するときは、「+*」の順序で記述する。
  • 「+」と「**」を両方指定するときは、「+**」の順序で記述する。
  • 継承元クラスに存在しないメソッドを継承しようとしたときや、継承元クラスに存在するメソッドと同名のメソッドを継承なしに定義した場合はコンパイルエラーとなる。
継承の仕様

ctorとcmp

kuin@Classに定義されているメソッドのうち、「ctor」「cmp」は継承可能です。

ctor

ctorメソッドを継承すると、コンストラクタ(インスタンス生成時の初期化処理)が実装できます。 ctorメソッドの定義はkuin@Class.ctorメソッドの定義の通りです。
kuin@Class.ctorメソッドの定義

 func ctor()

ctorメソッドを継承しない場合、何も処理をしない空のメソッドになります。 ctorメソッドの実装例はctorメソッドの実装例の通りです。
func main()
  class Test()
    +var a: int
    *func ctor()
      do me.a :: 5
    end func
  end class
  
  var test: Test :: #Test
  do cui@print(test.a.toStr() ~ "\n")
end func
ctorメソッドの実装例
このプログラムを実行すると、「#Test」の段階でTestクラスのctorメソッドが呼ばれ、最終的に画面には「5」が表示されます。

cmp

cmpメソッドを継承すると、クラスの比較処理が実装できます。 cmpメソッドの定義はkuin@Class.cmpメソッドの定義の通りです。
kuin@Class.cmpメソッドの定義

 +func cmp(t: kuin@Class): int

t 比較対象の値。 通常、自身のクラスの型を記述する
戻り値 比較対象の値よりも大きければ正、小さければ負、等しければ0を返す
cmpメソッドを継承しない場合、比較時に例外(E9170004)が発生し、比較できないクラスとなります。 cmpメソッドの使用例はcmpメソッドの実装例の通りです。
func main()
  class Test()
    +var a: int
    +var b: int
    +*func cmp(t: Test): int
      if(me.a + me.b > t.a + t.b)
        ret 1
      elif(me.a + me.b < t.a + t.b)
        ret -1
      else
        ret 0
      end if
    end func
  end class
  
  var test1: Test :: #Test
  do test1.a :: 2
  do test1.b :: 3
  var test2: Test :: #Test
  do test2.a :: 4
  do test2.b :: 5
  
  do cui@print((test1 >= test2).toStr() ~ "\n")
end func
cmpメソッドの実装例
この例ではTestクラスの比較方法を、aとbの和で定めています。

クラスのキャスト

クラスのインスタンスは、そのクラスとその継承元クラスの型にのみ変換できます(継承元クラスへの代入)。
func main()
  class Parent()
  end class
  
  class Child(Parent)
  end class
  
  var parent: Parent :: #Child
end func
継承元クラスへの代入
ただし継承先クラスに変換する場合には、「$」演算子によって明示的にキャストしないとコンパイルエラーになります。 このときインスタンスが、そのインスタンスのクラスおよび継承元クラスの型に変換される場合には変換できますが、継承先クラスに変換される場合には例外(E9170001)が発生します(継承先クラスへの代入)。
func main()
  class Parent()
  end class
  
  class Child(Parent)
  end class
  
  var parent: Parent
  
  do parent :: #Child
  var child1: Child :: parent $ Child {キャスト成功}
  
  do parent :: #Parent
  var child2: Child :: parent $ Child {キャスト失敗}
end func
継承先クラスへの代入
キャストに成功するかどうかは「=$」もしくは「<>$」演算子で判断できます。
1513347061ja