= クラスとオブジェクト

Konoha のオブジェクト指向プログラミングは、
名前ベースのクラス(nominal class)、単一継承(single-inheritance)など、
Java から強い影響を受けています。
また、スクリプト変数や関数なども、実は Script クラスのフィールド、メソッドとして
オブジェクト指向モデルの上で実現されています。

一方、Java 風の「あらかじめ厳密にクラス設計を行うプログラミング」とは一線を画し、
Konohaでは、緩やかな変更で微調整できる設計思想を導入し、
スクリプティング言語としての特性を活かせるようになっています。

== クラスの定義

新しいクラスは、class 文を用いて定義します。

クラスには、Java 同様、
フィールド変数[[Footnote(Javaでは、フィールドと呼びますが、Konohaは仮想フィールドと区別するため、フィールド変数と呼びます。)]]、
メソッド、コンストラクタなどのメンバーを含めることができます。

Konoha は、スクリプティング言語のダイナミックさを取り入れるため、
実行時にメンバーを追加することが可能になっています。そのため最低限、
クラス宣言時に必要なメンバーは、フィールド変数のみになります。

まず、フィールド変数のみ宣言された簡単なクラスからみていきましょう。

{{{
>>> class Person {
...   String name;
...   int age;
... }

}}}

Person クラスには、コンストラクタが定義されていませんが、
オブジェクトリテラルを使うことで、
データとして新しいオブジェクトを生成することができます。

{{{
>>> p = Person {name: "naruto", age: 12};
>>> p
main.Person {name: "naruto", age: 12}

}}}

オブジェクトのフィールド変数には、
フィールドアクセサを用いて、アクセスしたり、変更することができます。

{{{
>>> p.name
"naruto"
>>> p.age = 17
>>> p
main.Person {name: "naruto", age: 17}

}}}

Konoha では、コンパイル済みのコードに対して型安全であれば、
実行時にメソッドを追加したり、その振る舞いをかえることができます。

{{{
>>> boolean Person.isChild() {
...   return this.age < 21;
... }
>>> p.isChild()
true

}}}

== フィールド

フィールド変数は、オブジェクトの内部状態を記録する変数です。
クラス宣言のときに、あらかじめ宣言しておく必要があります。

=== フィールド変数宣言

フィールド変数は、アンダースコア(_)の接頭辞がついた名前で宣言します。
これは、Java プログラミングでよく用いる慣習に由来し、ローカル変数とフィールドを区別するためです。

{{{
class Person {
   String _name;
   void setName(String name) {
     _name = name;
   }
   ...
}

}}}

実際、前節の例でみてきたとおり、
変数名の接頭辞にアンダースコアをつけなくても宣言することができます。
（こちらの用例の方がより一般的でしょう。）
このとき、Konohaコンパイラは勝手に接頭辞にアンダースコアを追加し、
あわせて、自動的に getter/setter メソッドが生成されます。

{{{
class Person {
   String name;    // _name と解釈し、 getter/setterの自動生成
   
   String getName() {  // 自動生成
     return _name;
   }
   void setName(String name) {　　// 自動生成
     _name = name;  
   }
   ...
}

}}}

フィールド変数をどちらの形式で宣言しても、メソッドからフィールド変数へアクセスするときは、
_name のように アンダースコアを接頭辞につける必要があります。

=== フィールドアクセサ

Konohaは、全てのフィールド変数はいわゆる private です。

オブジェクト外部からフィールド変数への直接参照はできず、
全て getter/setter メソッドを経由しておこないます。

{{{
>>> p = Person {name: "naruto", age: 17};
>>> p.getName();
"naruto"
>>> p.setAge(18);
>>> p.getAge();
18

}}}

これはご存知のとおり、Javaプログラミングから広がったトレンドですが、
フィールドアクセスにいちいち getter/setter メソッドを不便に感じる人も多いでしょう。

Konohaでは、フィールドアクセサ({{{.}}}演算子)を、
getter/setter を呼び出すための省略形(シンタックスシュガー）として
再利用しています。

{{{
>>> p = Person {name: "naruto", age: 17};
>>> p.name;                   // 実は p.getName()
"naruto"
>>> p.age = 18;               // 実は p.setAge(18)
>>> p.age;
18

}}}

逆に、getter/setter メソッドが存在しない場合は、
フィールドアクセサから値を得たり、変更することはできません。

{{{
>>> class Person {
...   String name;
...   int _age;  // 年齢は秘密
... }
>>> p.age              // p.getAge() はないので
 - [(shell):10]:(error) undefined method: Person.getAge

}}}

応用例として、バーチャルフィールドを紹介しておきます。
これは、仮にフィールド変数の実体がなくても、
getter/setter を作ることで、あたかもフィールドが存在するように
見せられる機能です。

{{{
>>> String getFirstName() { 
...      return _name.twofold(" ").first;
... }

>>> p = Person{name :"naruto uzumaki", age: 17};
>>> p.name             // 実は p.getName()
"naruto uzumaki"
>>> p.firstName        // 実は p.getFirstName()
"naruto"

}}}

=== this.name と _name の違い

キーワード this は、自オブジェクト参照への参照です。
thisを経由して、フィールドアクセスすると、
フィールド変数を直接参照する代わりに、
ご想像のとおり、getter/setter を経由してアクセスすることになります。

{{{
class Person {
   String name;
   String getFirstName() {
      // this.name は、this.getName() と同じ
      return this.name.twofold(" ").first;
   }
   ...
}

}}}

もちろん、this.getName()より、
_nameで直接フィールド変数を参照した方がより高速です。

また、this参照を不用意に用いると、自分自身を呼び出して
無限ループに陥ることがあります。特に、
getter/setter メソッド内は注意が必要です。

{{{
   String _name;                        // やってはいけない
   String getName() { return this.name;} 
   
}}}


[[include(KbookIndex)]]
[[include(KbookFooter)]]

== メソッド

メソッドは、オブジェクトに対してメッセージを送受信する手段です。
0個以上のパラメータを受け取り、0もしくは1つの戻り値を返すことができます。

{{{
class Person {
　　String name;
   int age;
   boolean isChild () {
     return (_age < 21);
   }
}

}}}



=== メソッド追加}
Java 言語では、class 文の中でのみメソッドを定義することができました。Konoha では、動的言語の柔軟さを実現するため、既存のクラスに対して、スクリプト中どこでも新たなメソッドを追加定義することができます。次のPerso.isChild()関数は、class Person 内で定義されたisChild() と同じ定義になります。

{{{
boolean Person.isChild () {
   return (_age < 21);
}
}}}

メソッド追加は、これからインスタンス化されるオブジェクトのみでなく、（追加した時点で）既にインスタンス化されたオブジェクトにも影響が及びます。

{{{
>>> Person p = new Person("naruto", 17);
>>> boolean Person.isChild () {
...   return (_age < 21);
... }
>>> p.isChild()
true
}}}

=== 抽象メソッド}

抽象メソッドは、メソッドのインターフェースのみ定義され、実装パートが定義されていないメソッドです。Konohaでは、メソッドにつづくブロックが存在しなければ、抽象メソッドと解釈されます。また、メソッドのコンパイルに失敗したとき、自動的に抽象メソッドとして扱われます。

{{{
class Person {
   String name;
   int age;
    ...
   boolean hasFriend();           // 抽象メソッド
}
}}}

抽象メソッドの本来の用途は、抽象クラスやインターフェースなど、クラス設計においてポリモーフィズムを実現する手段としての利用です。厳密なスタティック言語では、全ての抽象クラスが実装されていない限り、クラスのインスタンス化はできない。しかし、Konoha は、抽象メソッドが含まれているクラスであっても、インスタンス化を認めています。これは、ラピッドプロトタイピングにおいて、単純に抽象メソッドを未実装なメソッドとして扱うためです。

抽象メソッドを実行すると、実行時例外となります。

{{{
>>> p = new Person("naruto", 17);
>>> p.hasFriend()
AbstractMethod!!: Person.hasFriend()
}}}

我々は、実行前にスタティックな抽象メソッドを検査する機構を検討しています。現在のところ、実行時にisAbstract()|によって検査する方法しかない。

{{{
>>> String.isAbstract()
false
>>> Person.isAbstarct()
true
}}}

=== パラメータの初期値}

メソッドの多重定義(overloding)は、異なる型のパラメータを同じ名前で定義することです。オブジェクトプログラミング言語の標準的な機能として、C++やJava言語で広く採用されているが、Konoha はメソッド再定義をサポートしていない。その代替機能として、パラメータの初期値を設定できます。

{{{
class {
   ...
   void Person.say(String msg="hello") {
      OUT << _name << " says " + msg << EOL;
   }
}
}}}

初期値が設定されたパラメータは、Nullable 型となります。したがって、パラメータを省略すると、自動的に null が与えられたものと解釈され、設定された初期値が渡されます。

{{{
>>> Person.says;
void main.Person.says(String? msg);
>>> p.say("aloha");
naruto says aloha
>>> p.say();　　                    // 省略, p.say(null) と同義
naruto says aloha
}}}

Konoha は、メソッドの多重定義をサポートしていない理由は、パラメータ初期値を活用することで、多くの場合のメソッド多重定義のバリエーションをカバーできるからです。あわせて、マップキャスト機能やAny}型パラメータを活用することで、いくつもメソッドを多重定義することなしに、同等なプログラミングが可能となります。

=== メソッドのバージョニング}

Konoha は、複数のメソッド実装をバージョン管理する機構を備えています。まず、メソッドのバージョニングは、オリジナルなメソッドに対し、パラメータの型と戻り値の型はそのまま同じで、メソッド名にバージョンタグ(:tag)を付けることで作成できます。

次は、:JA|タグを付加して定義したsays()メソッドの日本語版です。

{{{
void Person.says:JA(String msg = "こんにちは") {
   OUT << _naame << "は、"　<< msg << "と言った．" << EOL;
}
}}}

注意：（まだ厳密に決まった仕様ではないが、）英大文字で始まるタグは、言語ロケール用に予約されています。小文字で始まるタグは、ユーザが自由に利用して構いません。

バージョニングされたメソッドは、呼び出すときに明示的にバージョンタグを付けることで呼び出すことができます。

{{{
>>> p.says();
naruto says hello
>>> p.says:JA();　　                    // 日本語版の利用
naruto はこんにちはと言った.
}}}

¥subsubsection{将来の拡張計画}

将来のKonohaでは、型による自動的なバージョン切り換えも導入を予定しています。この機構には、セマンティックプログラミングの意味タグ型を流用する予定であるが、セマンティックプログラミングとの一貫性に関して検討を必要としています。

次は、Person}クラスに対し、意味タグを追加して、意味タグ型 Person:JA}型の例です。意味タグ型は、同じタグが付けられたメソッドを優先して呼び出す出されることになります。

{{{
>>> Person:JA p = new Person("なると", 17);
>>> p.says();                           // says:JA()を利用する
naruto はこんにちはと言った.
}}}

== クラス関数}
¥index{くらすかんすう@クラス関数}
¥label{class_function}

クラス関数は、クラス名を直接レシーバにして利用できる特別なメソッドです。通常、メソッドは、クラスのオブジェクトを操作するための手段です。したがって、メソッドを利用するとき、クラスがインスタンス化されている必要があります。しかし、特定のインスタンスから独立しており、インスタンスを特定できない、もしくはする必要がない場合があります。


乱数生成メソッド random()|は、特定の数値（インスタンス）の操作というより、それに独立したユーティリティ機能となります。ただし、Int} や Float} クラス程度に操作を区別する必要もあります。Konoha では、これらは、クラス関数としてそれぞれ定義されて提供されています。

{{{
>>> Int.random()
143980198322
>>> Float.random()
0.39810
}}}

クラス関数は、メソッド定義のとき、@Static| アノテーションを付けることで定義することができます。

{{{
@Static
int Int.max(int a, int b) {
   return (a > b) ? : a : b;
}
}}}

@Static|アノテーションは、Java のスタティックメソッド¥index{すたてぃっくめそっど@スタティックメソッド}に由来しています。事実、見かけ上、クラス関数はスタティックメソッドと同様に利用することができます。しかし、実際はクラスのデフォルト値をレシーバとしてメソッドを呼んでいます。this} キーワードを用いれば、自オブジェクトとして参照もできます。

{{{
>>> Int.max(1, 2)
2
>>> (default(Int)).max(1, 2)     // 同じ
2
}}}

また、シングルトンクラスは、@Static|アノテーションがなくても、自動的にクラス関数として解釈されます。そのため、クラス関数としてコールしてもよいし、メソッドとしてコールしても構いません。

{{{
>>> System.exit()                // System はシングルトン
>>> os = default(System)
>>> os.exit()                    // 同じ
}}}

Konoha は、シンプルな言語構造を実現するため、Java風のスタティックフィールドをサポートしていない。クラスで共有したい変数は、単にスクリプト変数を用いることができます。

== コンストラクタ}


== オペレータとメソッド}

Konohaでは、全てのオペレータはメソッドのシンタックスシュガーです。例えば、加算演算 x + y| は、次のように単純にメソッドopAdd()|に置き換えられて実行されています。

{{{
x.opAdd(y)                            // x + y
}}}

そこで、演算子と対応つけられたop| で始まるメソッドを定義すれば、オペレータの振る舞いを変更することも可能です。ただし、演算子の再定義は、Konohaではあまり積極的に推奨されない。

¥begin{tabular}{llll}
x + y| & x.opAdd(y)| & x - y| & x.opSub(y)| ¥¥
x * y| & x.opMul(y)| & x / y| & x.opDiv(y)| ¥¥
x mod y| & x.opMod(y)| & & ¥¥
¥verb/x++/ & x = x.opNext()| & ¥verb/x--/ & x = x.opPerv()| ¥¥

x == y| & x.opEq(y)| & x != y| & x.opNeq(y)| ¥¥
x < y| & x.opLt(y)| & x <= y| & x.opLte(y)| ¥¥
x > y| & x.opEq(y)| & x >= y| & x.opNeq(y)| ¥¥

x & y| & x.opLand(y)| & ¥verb/x | y/ & x.opLor(y)| ¥¥
x ^ y| & x.opXor(y)| & ‾x| & x.opLnot(y)| ¥¥

x << y| & x.opLshift(y)| & x >> y| & x.opRshift(y)| ¥¥
¥verb/|x|/ & x.getSize()| & ¥verb/y in? x/ & x.opHas(y)| ¥¥

x[n]| & x.get(n)| & x[n] = y| & x.set(n)| ¥¥
x[] = y| & x.setAll(n)| & x[s..e]| & x.opSubsete(s,e)| ¥¥
x[s..<e]| & x.opSubset(s,e)| & x[s..+n]| & x.opOffset(s,n)| ¥¥
¥end{tabular}

¥begin{comment}
== フォーマッタの定義}

=== フォーマッタメソッド}

You can define or add new formatters as methods, since formatters are a specialized method with the following signature.

{{{
void Object.%fmt(OutputStream w, String fmt) ;
}}}

Formatting is designed to output data to OutputStream. 

{{{
void Person.%xml(OutputStream w, String fmt) {
   w << "<person name='%s{0}'/>" %% _name << EOL;
}
}}}

{{{
>>> p = new Person("naruto", 17);
>>> %xml(p)
<person name='naruto'/>
}}}

== マッパーの定義}
¥end{comment}

¥chapter{クラス継承と抽象化}

クラス継承(class inheritance)は、オブジェクト指向プログラミング黎明期の一大関心事であった。しかし、オブジェクト指向プログラミングが広く普及し、多種多様なオブジェクトのデザインパターンが実践されるにつれ、それほど関心を集める話でなくなった。

Konoha は、そんな時代に設計されたので、「クラス継承」に関して、必要最小限の機能をサポートするのみにとどめています。（しかも、現在のところ、ほとんどクラス継承を使う機会はない。）

== クラス継承} ¥label{class_inheritance}

Konoha のオブジェクト指向プログラミングは、Javaから強い影響を受けています。クラス継承を用いるクラス定義は、Java同様、 class文においてextends} 節によって上位クラス$D$を指定することができます。クラス継承によって定義されたクラス$D$は、上位クラス$C$に対し、「サブクラス(subclass)」と呼ぶ。

¥begin{quote}
class | $D$  extends | $C$  {| ¥¥
  | $members$ // クラスのメンバー ¥¥
}| ¥¥Konoha は、Javaのオブジェクト指向プログラミングの特徴を強く受け継いで設計されています。
¥end{quote}

クラス継承とは、上位クラスの振る舞い、つまりメソッドを引き継ぐことです。サブクラスでは、上位クラスのメソッドを継承するのみならず、新たなメソッドを追加することもできます。次のクラスD}は、クラスC}のサブクラスです。メソッドC.sayHi()|を継承し、新たにD.sayBye()|を追加しています。

{{{
>>> class C {
...    void sayHi() { print "hi"; }
... }

>>> class D extends C {
...    void sayBye() { print "bye"; }
... }

>>> D d = new D();
>>> d.sayHi()           // c.sayHi()が呼ばれる
hi
>>> d.sayBye()          // 追加されたメソッド 
bye
}}}

=== final} クラス}

Konoha では、クラス定義において、Java 言語同様、final}修飾子、もしくは@Final}アノテーションを付けることで、クラス継承不可能なクラスとして宣言できます。

{{{
final class C {
   void sayHi() { print "hi"; }
}

class D extends C {    // C は継承できない
   void sayBye() { print "bye"; }
}

}}}

== オーバーライド}

オーバーライドは、継承されたメソッドをサブクラスにおいて上書き、つまり新たに作り直す機構です。オブジェクトに対しポリモーフィズム(polymorphism)を与える重要な機構であるが、同時に、ダイナミックバインディングによる性能低下が議論となる機構でもあります。

Konoha は、C++ や C¥#の流儀にしたがって、@Virtual}アノテーションが付けられたメソッドのみオーバライドすることができます。これは、実際のプログラミングにおいて、メソッドがオーバーライドされることは稀であり、Java のようにデフォルトでオーバーライドを認めることによる性能ロスを無視できないと判断したためです。プログラマがダイナミックバインディングを避けるためfinal}を追加するようなテクニックを駆使することなく、ふつうに書いて最適な速度が得られる方を好んだといえる。

{{{
class C {
   @Virtual void sayHi() { print "hi"; }
}

class D extends C {    
   // オーバライド
   @Override void sayHi() { print "Hey"; }
   void sayBye() { print "bye"; }
}
}}}

注意： @Virtaul} メソッドは、ダイナミックバインディングされるため、どうしてもスタティックバインディングに比べると遅くなります。Konoha では、インラインキャッシュによる高速化の工夫をしているが、オーバーライドする必要のないメソッドは@Virtual 宣言しないようにすべきです。また、抽象メソッドもオーバーライドされたメソッドも、同様に、ダイナミックバインドされます。

=== ポリモーフィズム}

== super}}

{ｴsf super} は、上位クラスのフィールドやメソッドへアクセスするためのリファレンスを表す表現です。

== インターフェース*}

Konoha は、Javaと同様に、単一継承(single inheritance)です。複数のクラスの振る舞いを継承するクラスを定義したいときは、インターフェースを実装する方法を用います。次は、クラス$D$とクラス$E$のインターフェースを実装することを宣言したクラスです。

¥begin{quote}
class | $C$  implements | $D$, $E$  {| ¥¥
  | $members$ // クラスのメンバー ¥¥
}| ¥¥
¥end{quote}

Konoha は、Java と異なり、インターフェースを定義する専用のinterface} 文は存在しない。その代わり、任意のクラスをインターフェースとして実装することができます。

{{{
>>> class C {
...    void sayHi() { print "hi"; }
...    void sayBye() { print "bye"; }
... }

>>> class D implements C {
...    void sayHi() { print "Hai"; }
... }
>>> D d = new D();
>>> d.sayHi()                      // 自分で作る
Hai
>>> d.sayBye()                     // 継承されない
 ** AbstractMethod!!
}}}

注意: インターフェースは、あくまでもメソッドの設計（シグネチャ）のみ継承し、実装は継承しない。Konoha では、抽象メソッドとして継承されます。そのため、新たに追加しない限り、implements} されたインターフェースのメソッドは、Abstract!!|例外になります。

=== インターフェースへのメソッド追加**}

== Object} クラス}

Object} クラスは、全てのクラスの共通した上位クラスです。全てのオブジェクトは、Object}クラスのメソッド（オペレータ、フォーマッタも含む）を継承しています。

