ページの移動
このページの目的
Cookerは、Webページを操作するためのアプリケーションですから、操作のターゲットとなるページを読み込む必要があります。
このページでは、ターゲットページに移動するスクリプトを作成することで、ページ移動関連の処理とRice言語の構成要素について学んでいきます。
目次:
ペインとブラウザ
Cooker は二ペインのアプリケーションです。このページのRiceコードは左側のペイン、Main-ブラウザ、で実行されると仮定されて実装されています。
右側のペインでも実行できますが、実行の結果はMain-ブラウザに現れます。
宣言文
簡単なページ移動スクリプトを以下に示します。これはCookerを https://www.example.com/ に移動するためのスクリプトです。
1: | class main |
2: | // ブラウザを example.com へ移動する。 |
3: | open method void start() |
4: | browser br; // 宣言文。browserクラスの変数"br"を作成。 |
5: | br.LoadUrl("https://www.example.com/"); // browserクラスのLoadUrl(string)メソッドの呼出。 |
6: | endmethod |
7: | |
8: | open method void end() |
9: | endmethod |
10: | endclass |
前ページのテンプレートスクリプトに二行加えたものです。なお、以下の説明はコメントの存在を無視しています。
ここでは、四行目に注目してください。"browser"というワードに"br"が続き、セミコロン(;)で終わっています。
このようなワード並びで、以下の条件を満たすものを宣言文といいます。
最初のワードはクラス名でなければいけません。この場合は、browserクラスを示す"browser"を指定しています。
クラスとは、状態と操作のグループに名前が付いたものです。Cookerでは "browser" という名前でブラウザの状態と操作機能群が定義されています。
二番目のワードは変数名です。ここでは、適当に"br"という名前を使っています。
変数名の命名規則や変数そのものについては後述します。ここでは、"br"が変数名として有効であると理解してもらえば十分です。
最後がセミコロン(;)です。これは、文の終わりを示す記号です。
宣言文とはスクリプトへの名前の導入です。上記の宣言文ならば、名前 "br" と、その中身が "browser" クラスであることをCookerに教えています。
"browser" クラスの変数は定義なしで使うことが出来ます。その場合はMain-ブラウザを表します。
LoadUrl(string) - 呼出文
次は五行目です。五行目にあるワード並びは、四行目で宣言した"br"の後に "." が続き "LoadUrl("https://www.example.com/");" で終わっています。
このようなワード並びを呼出文といいます。呼出文で重要なのはドット(.)です。これは、ドット演算子と呼ばれる演算子で、Cookerに"メンバ"の呼び出しを指示しています。
新しい用語がいくつか出てきましたが、それらについては後述します。
四行目の宣言文によってCookerは "br" が "browser"クラスであると知っています。この"br"に、ドット(.)、"LoadUrl"と続くことによって、Cookerは「browserという機能群の中の "LoadUrl" を呼び出す」という意図を知ることができます。
"LoadUrl"には幾つかの種類があります。そこで、"LoadUrl"と後続する ("https://www.example.com/") から正確な名前"LoadUrl(string)"を作成して呼び出し対象を確定します。
"LoadUrl(string)" に割り当てられている機能はブラウザの移動です。移動に必要なURLを"https://www.example.com/"で "LoadUrl(string)" に渡しています。最後のセミコロン(;)が文の終わりを示します。
この呼出文が実行されるとCookerのブラウザが "https://www.example.com/" へ移動を開始します。
スクリプトの実行
上記のサンプルを適当なファイルに書き出して実行すると、example.com が表示されます。
以降は、書き出したファイルの名前が "example.cook" であるとして説明します。
上記の例をファイルに書き出す際は、行番号を削除してください。これは、説明のためのもので、スクリプトの実行には必要ありません。
"example.com" は、実例として使用するために用意されているドメインであり、文献中で使用することが許可されています。
"example.cook" はURLへ移動するだけのスクリプトですが、"https://www.example.com/" の部分を書き換えれば希望のURLへ自由にジャンプできます。
"browser" クラスは "LoadUrl"のような機能を他にも多数持っています。更に、"browser"のようなクラスが他にもたくさん組み込まれています。
これらの組み合わせで、あなたが望む機能を新たに生み出すことができるのです。
クラス
ここまでのサンプルスクリプトではmainクラスを定義してきました。前のセクションで述べたとおりに、"main" 以外のクラスも自由に定義できます。
この様なCookerの利用者が独自に定義するクラスをユーザ定義クラスと呼びます。そして、クラスには他に幾つかの種類があります。
Cookerは、ユーザ定義クラスではない予め定義されたクラスを持っています。それを、ここでは組み込みクラスと呼びます
組み込みクラスには三つの種類があります。Rice基本クラス、Cookerビルトインクラス、Cooker埋め込みクラスです。
Rice基本クラス : 全てのRiceスクリプトで共通に利用できるクラス。数値、文字列などの基本要素。
Cookerビルトインクラス : Cooker上のRiceスクリプトだけで利用できるクラス。ウインドウやブラウザなどのCookerの構成要素。
Cooker埋め込みクラス : Cooker起動時に動的にロードされるクラス。機能拡張クラス。
例えば、"数値"を扱わないプログラムは無いでしょう。
例えば、Cookerには"ブラウザ"が部品として組付けてあります。その"ブラウザ"がユーザ定義クラスから高頻度で操作されることは、容易に予想できます。
このような、多数から利用される部分を予め用意したのが組み込みクラスです。前述のbrowserクラスは、この様な組み込みクラスの一つです。
組み込みクラスの一覧はここから確認できます。
メンバ
Riceにおいてメンバという用語は、"クラスの構成要素"を意味しています。
メンバの種類を以下に示します。
フィールド(field)
フィッタ(fitter)
セッタ(setter)
ゲッタ(getter)
メソッド(method)
個々のメンバについての詳細はリファレンスを参照してください。
先に出てきたLoadUrlは、browserクラスのメンバであるLoadUrlメソッドになります。
変数と名前
Riceにおける変数の定義は、以下の様になります。
変数は、インスタンスのアドレスを保持するメモリ領域のことです。
アドレスを保持しているので参照型変数です。名前で識別され、クラスに拘束されます。
インスタンスとは、クラスの実体であるデータ群です。通常は、アドレスで識別される連続するメモリ領域に保持されます。
Riceにおける変数の詳細は、リファレンスをご覧ください。
上記の定義をチュートリアルに相応しい説明に直します。
"変数"とは「名前の付いた容器」です。更に、上記のようにクラスが結び付けられるので、入る物の種類(クラス)は決まっています。
容器ですから中身の入れ替えができます。しかし、入るもの(クラス)は決まっているので、他のクラスは入れられません。
変数の命名規則は以下の様になります。
使える文字は半角文字。全角文字は使用不可。
最初の一文字はアンダースコアかアルファベット。その後、アンダースコア、アルファベット、または数字が0回以上繰り返す。
大文字と小文字は区別される。
文字数に制限はない。
予約語は名前に使用できない。予約語とは、キーワードと組み込みクラスのクラス名である。
命名規則の詳細はリファレンスを参照してください。
変数の命名規則は、ユーザー定義の"名前"の命名規則でもあります。クラスやメンバーなどの、ユーザー定義要素の"名前"は、この規則にしたがって命名されなくてはなりません。
ドット演算とメンバ呼び出し
ドット演算子は、演算子の左側のクラスのメンバを呼出すための演算子です。上記の例は、ドット演算子の左側がbrowserクラスの変数なのでbrowserクラスのメンバを呼び出します。
演算子の左側は変数に限られるわけではありません。左側のクラスが決定できれば、そのクラスのメンバを呼び出します。
上記の例は、browserクラスのメンバであるLoadUrl(string)メソッドを呼び出しています。メソッドは呼び出し時に0個以上の値を渡すことが可能なメンバです。この値のことを引数といいます。
引数の数とクラスはメソッド毎に厳密に決まっています。LoadUrl(string)メソッドは引数としてURL文字列を一つ渡すように決まっているので、"https://www.example.com/"を引数として渡しています。
引数が無い場合や二つ以上ある場合の表記法についてはリファレンスを参照してください。
文とセミコロン
宣言やメソッド呼出などのような、意味のあるワードの並びを文といいます。
文の終了は、セミコロン(;)で示します。実際、宣言文も呼出文も最後にセミコロンが必要です。
ただし、文の中には、セミコロンで終わらないものもあります。それらについては、後で説明したいと思います。
イベント処理
現在の"example.cook"は、example.com へ移動を指示したら、移動の完了を待たずに終了してしまいます。使用したLoadUrl(string)メソッドがそのように実装されているからです。
ページの移動には時間がかかるかもしれませんし、移動が失敗するかもしれません。移動後のページに操作を行うためには、"ページ読込みが完了しているのかどうか"を判定しなければいけません。
読込みが完了しているのかどうかを判定する方法は幾つかありますが、ここではイベント処理を利用してみましょう。
イベントとは、アプリケーション内で発生したマウスのクリックや文字の入力のような事象のことです。
事象に名前をつけて、発生を検知し、対応するプログラム(イベントハンドラ)を呼び出すシーケンスをイベント処理といいます。
読込みが完了しているのかどうかを判定するために、ここでは "browser" クラスの"LoadCompleted"イベントを利用します。
このイベントのイベントハンドラは、"browser" クラスのLoadCompleted(class,string)メソッドで割り当てます。
それでは、"example.cook"に、その為のコードを加えてみましょう。
1: | class main |
2: | // ブラウザを example.com へ移動。読み込み完了の捕捉。 |
3: | open method void start() |
4: | browser br; |
5: | switch sw = br.LoadCompleted(this, "LCHandler(dictionary)"); // LoadCompletedイベントにハンドラを割り当てる。 |
6: | sw.Start(); // イベント処理開始。 |
7: | br.LoadUrl("https://www.example.com/"); // 移動 |
8: | endmethod |
9: | |
10: | open method void end() |
11: | endmethod |
12: | |
13: | open method void LCHandler(dictionary dic) |
14: | message m; // メッセージ表示用のクラス。 |
15: | m.Show("LoadCompleted イベント発生!"); // メッセージ表示。 |
16: | endmethod |
17: | endclass |
五行目で、イベントへ "main" クラスの LCHandler(dictionary)メソッドを割り当てています。このメソッドがイベントハンドラになります。
六行目で、イベント処理を開始しています。
五行目は定義文です。定義文は変数の宣言と初期化を同時に行うものです。
"switch"クラスの変数"sw"を宣言して、その内容として"="記号の右辺(br.LoadCompleted(this, "LCHandler(dictionary)"))の結果を設定します。
"="記号は代入演算子です。演算子の右辺の結果を左辺に代入します。演算子の左右のクラスは一致しなければなりません。br.LoadCompleted(this, "LCHandler(dictionary)")は"switch"クラスを返す様に実装されているので、"sw"に代入することが出来ます。
LoadCompleted(this, "LCHandler(dictionary)")の詳細については、browser クラス : LoadCompleted(class, string)メソッドをご覧ください。
LoadCompleted(this, "LCHandler(dictionary)")のなかで、キーワード"this"が使われています。これは、"class" や"endclass"のように特別な意味を持ちます。
"this"キーワードはthis演算子を表します。this演算子はユーザー定義クラスのインスタンスを返す式です。どのユーザー定義クラスを返すかは、それが現れた場所によって決まります。この場合は、"main"クラスの定義の中で出てきたので、"main"クラスのインスタンスを返します。
LoadCompleted(class,string)メソッドは"switch"クラスのインスタンスを返します。
この場合は、"LoadCompleted"イベントにたいして、"main"クラスのLCHandler(dictionary)メソッドを呼び出す様に設定した"switch"を返します。
六行目で、"sw"のStart()メソッドを呼び出して、イベント処理を開始しています。
Start()の詳細については、switch クラス : Start()メソッドをご覧ください。
フィールド
上記の"example.cook"には、二つ問題が残っています。
一つ目 | イベント処理が停止されていない。 |
二つ目 | ページ読み込みの成功が判定されていない。 |
問題を修正したのが、以下のコードです。
1: | class main |
2: | browser br; // フィールドを宣言。 |
3: | switch sw; |
4: | message m; |
5: | open method void start() |
6: | sw = br.LoadCompleted(this, "LCHandler(dictionary)"); // フィールドに代入。 |
7: | sw.Start(); // イベント処理開始。 |
8: | br.LoadUrl("https://www.example.com/"); |
9: | endmethod |
10: | |
11: | open method void end() |
12: | sw.Stop(); // イベント処理停止。 |
13: | endmethod |
14: | |
15: | open method void LCHandler(dictionary dic) |
16: | if(dic.IsSuccess) // if文 |
17: | m.Show("ページロード成功。"); |
18: | else |
19: | m.Show("ページロード失敗。"); |
20: | endif |
21: | endmethod |
22: | endclass |
二行目から四行目:
メソッド定義内で宣言されていた変数 "br"、"sw"、"m"の宣言は、メソッド定義内から移動されました。
全てのメンバ定義の外で宣言された変数を、特にフィールドと呼びます。
フィールドと変数の違いは、その参照範囲です。変数は、それが置かれている定義内でしか参照することができません。フィールドはクラスの全ての定義内から参照できます。
このような参照範囲のことをスコープといいます。クラス内の様々な定義で共用したい変数はフィールドとして宣言します。
十一から十三行目:
前ページで説明したとおりにend()メソッドはスクリプトの終了時に呼び出されます。ここで、sw.Stop()を呼び出すことでイベント処理が停止されることが保証されます。
詳細については、以下のリンクをご覧ください。
if文
十六~二十行目:
キーワード"if"から始まり、"endif"で終わるワードの列をif文と呼びます。
if文は、"if"に続く括弧内の式によって処理を分岐するための文です。
"LoadCompleted"イベントが発生すると、ハンドラが呼ばれます。このとき、ハンドラのdictionaryクラスの引数に"LoadCompleted"イベントに関連する情報が自動的にセットされます。
"dic.IsSuccess"は自動的にセットされた情報の一つで移動の成功判定です。"dic.IsSuccess"が真なら移動成功です。偽なら失敗になります。
成功か失敗に応じて処理を分岐します。ここでは適切なメッセージを表示しています。
if文の詳細については、if文をご覧ください。
if文は文ですが、"endif"の後にセミコロンが続かないことに注意してください。これが、セミコロンで終わらない文の例です。
if文は内部に他の文を含むことが出来ます。上記の例では、以下の文が含まれています。
m.Show("ページロード成功。");
m.Show("ページロード失敗。");
このような、内部に他の文を含むことが出来る文は他にもいくつかあります。それらはセミコロンを使わずにキーワードで文の終了を示します。
文の詳細については、Riceにおける文をご覧ください。
if文の分岐によって実行されるコードを適切なものに入れ替えることにより、移動の成功と失敗の、それぞれに相応しい処理を行うことができます。