Ceylonのコードを書くときの基本的な書き方をやります。
まずはCeylonのプロジェクトが出来ている前提です。
出来ていない人は Ceylon環境の作り方からどうぞ。
#まずモジュール作成
New > Ceylon Module
からモジュール作成のダイアログを開きます。
Module nameに入力した値はパッケージ名になります。
Runnable compilation unitに入力した値は実行のファイル名になります。
上記のように入力して完了すると
以下のファイルが作成されます。
module.ceylon
package.ceylon
run.ceylon
module.ceylonにはモジュールで利用するライブラリなどの読み込み設定などを書くようです。
package.ceylonにはパッケージのドキュメントを書いたりするとこみたいです。
Javaでのpackage-infoみたいな感じ?
run.ceylon通常のCeylonソースコードを書いて行く場所です。
run.ceylonを開くと
shared void run() {
}
と書かれているのでそのメソッドの中にバリバリ書いて行けばOKです!
#クラスの作り方
と言うことでちょっとずつ実践的な感じにするために
絶対必須なクラス定義のしかた。
前回のCeylonの良いとこ説明コードその1で触れたとこは
特に説明しないのでvariableとかは前回の投稿を見てね。
と、言うことで早速クラス書いちゃいます。
shared void run() {
value counter = Counter();
print(counter.inc()); // -> 1
print(counter.inc()); // -> 2
print(counter.inc()); // -> 3
}
class Counter() {
variable Integer i = 0;
shared Integer inc() {
return ++i;
}
}
run.ceylonファイルに
Counterクラスを書いてみました。
なんとCounterクラスをインスタンス化するのにnewがありません!
最初は違和感があるけど、慣れればあんまり気になりません。
ただ、ちゃんと大文字からクラス名を付けないとクラス生成してるのか
メソッドを呼んでるのか分かんなくなりそう。
まあJavaをやっていれば既に雰囲気はつかんでると思います。
#メソッド、公開変数、などのスコープ
Counterの保持する「i」はクラスの外には見えません。
クラス外に見えるようにするにはsharedを付けます。
protectedなスコープを持つ変数は定義出来ません。
次にincメソッドですがsharedがついているのでクラス外から呼び出すことが出来ます。
外すとクラス内からのみアクセス可能なメソッドになります。
最後にクラスにsharedを付けるとどこからでもクラスを参照することが出来ます。
何も付けていないときは同じパッケージ内の場所からのみ参照出来ます。
ファイルが別でもパッケージが同じであれば参照可能です。
Javaのprotectedとパッケージプライベートの扱いって微妙でしたよね。。
どう使っていいか困ったこともあります。。
でも、Ceylonでは完全に割り切ってる感じでシンプルだなと。
#デフォルト引数
Ceylonではメソッドにはデフォルト引数が使えます。
incメソッドに引数に与えた数値分増加出来るようにしてみました。
shared Integer inc(Integer add=1) {
return (i += add);
}
デフォルト引数が可能にはなっていますが、
代わりにJavaでは出来たメソッドのオーバーロードが出来なくなっています。
ま、良いんじゃないかな。デフォルト引数値はC#やScalaを指くわえながら見て
欲しいなーと思っていたのであった方がいいよね!
#コンストラクタ
まず、クラスがメンバを持つ場合、全て初期化しないとコンパイルエラーとなります。
今回は i に 0 をセットしてます。
この辺もCeylonの細やかな厳しさを感じる。
Javaにグッときてる人は逆にいいんじゃないかなと思う。
ここではコンストラクタでカウンターの初期値を設定して生成出来るようにしてみましょう。
class Counter(variable Integer i=0) {
shared Integer inc(Integer add=1) {
return (i += add);
}
}
はい。メンバ変数で定義してたヤツが居なくなりました!
なんと、コンストラクタで引数として受け取った変数は
自動でメンバ変数として保持されます。
外部から参照されるようにしたい場合はこの「i」にsharedを付ければ
クラス外から参照出来るようになります。
ちょっと楽チン。
コンストラクタで何かチェックしたいときは
そのままコードを書けばOK.
初期値としてマイナスの数値が入った場合エラーにするようにすると
class Counter(variable Integer i=0) {
assert(i>-1);
shared Integer inc(Integer add=1) {
return (i += add);
}
}
こんな感じ。
マイナス値のときに自動で0にしちゃうようにしてみると
class Counter(variable Integer i=0) {
if(i < 0) {
i = 0;
}
shared Integer inc(Integer add=1) {
return (i += add);
}
}
こんな感じ。
メソッドなしでロジックやら初期変数が定義されたりですね。
複雑なコンストラクタが生まれるよりは1個のコンストラクタに集約されて
記述も身軽になって良いかも??
でもこの辺はJavaと感覚がちょっと違う感じかなぁ。
ここは使い込んでみないと良いのか悪いのか分からないかも。
#setterとgetter
setterとgetterの扱いが変わっています。
Javaでは命名規則でsetXxxxx、getXxxxというメソッドが
プロパティのsetter、getterと言う扱いでしたが、
Ceylonでは以下のように宣言します。
shared Integer nowCount {
return i;
}
assign nowCount {
i = nowCount;
}
getterは値を返すだけのものを付ければOKです。
この宣言は参照は出来ても代入は出来ません。
代入するにはsetterの宣言が必要です。
参照はこのように呼び出してコンソールに出力したり出来ます。
print(counter.nowCount);
setterはassignで宣言します。sharedは必要ありません。
assignを付けると自動的に公開状態になります。
以下のように代入で呼び出すことが出来ます。
counter.nowCount = 10;
ちなみに1行のときはこんな感じで書くことが出来ます。
shared Integer nowCount => i;
assign nowCount => i = nowCount;
やばいscalaっぽくなってきた。
でも、Java8も来そうだし、アリですよね!
#Javaでの宣言との比較
java -> ceylon
public -> shared
protected -> メソッドは無印で同じパッケージからアクセス可能
private -> 変数は無印でクラス内からでのみアクセス可能
コンストラクタは1つだけ!
デフォルト引数値を指定出来るようになった!
gettersetterはメソッド命名規則ではなくassignでsetterを、getterは別参照名で。
#まとめ
Javaと書き方が違うなーって感じるところもちょいちょい出てきました。
でも、Javaで微妙だ・・・って思っていたところが順々に改善されている感じが分かります。
スコープ、そしてデフォルト引数とsetter、getterそしてコンストラクタでした。
改善されているなぁ。
読み口はあまり変わらないまま読めるかなーと思います。
まあ、コンストラクタ内での処理とか、getterとsetter周りでは
scalaとか読んでればあんまり違和感無いかも知れないけど
Javaから見るとちょっと違和感が出てきたかも?
それでもJavaっぽい読み味は失われてません!
でも、ちょっと慣れが必要になって来る文が出てきたかも。
もうちょっとだけ頑張ってみて!