Section 2.7 オーバーライド

今回も継承の話の続きなんだけど、ちょっと気分を変えて新しいクラスを作ってみようと思うんだ。
うん、りょーかい。
それで、どんなクラスを作るの?
ファイルを選択するためのクラスだよ。
こういうダイアログボックスって見たことない?

<「ファイルを開く」ダイアログボックス>

「ファイルを開く」ダイアログボックス

あ〜、よく見かけるよね、これ。
これで開きたいファイルを選ぶんだよね。
そうそう。
で、今回はこのダイアログボックスを使って、開きたいファイルの名前を取得するためのクラスを作るの。
TJS ってそんなこともできるの?
うん、できるよ。
例えば、KAG でフリーセーブモードにすると、セーブやロードの時にファイル選択のダイアログボックスが表示されるでしょ。
あ、そういえばそうだね。
それじゃ、まずは簡単なクラスを作ってみるね。
うん。

<開きたいファイル名を取得するためのクラス:SimpleFileSelector クラス>

class SimpleFileSelector
{
    var fileName;  // 選択されたファイル名を保持するメンバ変数

    // コンストラクタ
    function SimpleFileSelector()
    {
        fileName = "";  // fileName を空文字列に初期化します
    }

    // デストラクタ(何もしません)
    function finalize(){}

    // selectFile メソッドに渡す辞書配列を返します
    function getParams()
    {
        var params = new Dictionary();

        params.filter = ["すべてのファイル(*.*)|*.*"];  // すべてのファイルを表示します
        params.initialDir = System.exePath;  // krkr.eXe があるフォルダを初期状態で表示するフォルダに指定します
        params.save = false;  // ダイアログボックスの種類は「保存」ではなく「開く」なので偽を指定します

        return params;
    }

    // 「ファイルを開く」ダイアログボックスを表示します
    // 『開く』ボタンが押された場合は選択されたファイル名を fileName にセットして真を返します
    // 『キャンセル』ボタンが押された場合は何もせず偽を返します
    function openFile()
    {
        var params = getParams();  // selectFile メソッドに渡す辞書配列を取得します

        if(!Storages.selectFile(params))  // 「ファイルを開く」ダイアログボックスを表示します
            return false;  // 『キャンセル』ボタンが押されたので偽を返します

        fileName = params.name;  // 選択されたファイル名を fileName にセットします

        return true;
    }

    // 選択されたファイル名を取得するための読み取り専用プロパティ
    property name
    {
        getter()
        {
            return fileName;
        }
    }
}  // SimpleFileSelector クラスの定義はここまで


// SimpleFileSelector クラスの使用例
var sel = new SimpleFileSelector();
if(sel.openFile())  // ファイルが選択された場合は、パス+ファイル名を表示します
    System.inform(sel.name, "選択されたファイル名");
invalidate sel;

じゃ、今回もまずは実行ね。
はーい。

「ファイルを開く」ダイアログボックス

「ファイルを開く」のダイアログボックスが表示されたね。
どれか適当なファイルを選んでみて。
じゃあ、krkr.eXe を選択して、「開く」、と。

表示されたメッセージ「file://./c/tjs/krkr.eXe」

? これってどういう意味?
tjs フォルダにある krkr.eXe っていうのは何となく解るんだけど、見たことない書き方だよ?
この形式は統一ストレージ名って言って、TJS ではこの形式でファイルのあるフォルダやファイル名を表してるんだ。
へぇ…そうなんだ。
さっきのスクリプトの最後から2行目のこの行を…

<書き直す前のスクリプト>

System.inform(sel.name, "選択されたファイル名");

こう書き直して実行すると、見慣れたファイル名になると思うよ。

<書き直した後のスクリプト>

System.inform(Storages.getLocalName(sel.name), "選択されたファイル名");

スクリプトを書き換えて、もっかい実行してみて。
うん、りょーかい。

表示されたメッセージ「c:\tjs\krkr.eXe」

あ、ほんとだ。これはよく見る書き方だね。
getLocalName っていうメソッドを使うと、この書き方に変換できるの?
ん、そう。Storages クラスの getLocalName メソッドは、 統一ストレージ名を OS ネイティブの形式に変換するメソッドなんだ。
だから Windows 上でこのメソッドを実行すると Windows で普通に使われてる表記に変換できるってワケ。
う〜ん、なんか難しいね…
まぁ、これは別に覚えなくても大丈夫だと思うよ。
そなの?
うん、普通はファイル名の表記をそんなに気にしなくても問題ないからね。
んじゃ、スクリプトの方を見ていこっか。
まずはメンバ変数からね。
fileName っていうメンバ変数があるね。
これに選択されたファイル名を保存しとくの。
なるほどね。
じゃあ次はコンストラクタデストラクタだけど、これは簡単だよね。
コンストラクタで fileName を空文字列に初期化してて、 デストラクタでは何もしてないね。
ん。じゃ次は getParams メソッドね。
辞書配列を作って、なんか色んな値を代入してるね。
この辞書配列は、ファイル選択ダイアログボックスを表示する時に、Storages クラスの selectFile メソッドに渡すんだ。
あ、そういえばさっきの getLocalName メソッドの時に聞き忘れてたんだけど、 Storages クラスって初めて出てくるクラスだよね?
Storages クラスはファイルやフォルダに関係するメソッドを扱ってるクラスだよ。
このクラスも System クラスみたいに元々用意されてるの?
うん。あと、System クラスと同じようにオブジェクトが作れないクラスなんだ。
getLocalName メソッドを呼び出すときに Storages.getLocalName って書いてあったもんね。
ん。で、selectFile メソッドには1つだけ引数があって、その引数に getParams メソッドで作った辞書配列を指定するの。
filterinitialDirsave っていう要素があるね。
まず、filter にはフィルタ文字列を指定するんだ。
フィルタ文字列って?
フィルタ文字列ってのは、ダイアログボックスに選択候補として表示されるファイルの種類を指定する文字列のこと。 つまり、「ファイルの種類」の欄に表示されるこれのこと。

<フィルタの例>

フィルタの例

あ〜、これのことね。
フィルタ文字列は配列で指定するんだ。
で、この例だと『ビットマップ』『JPEG』『PNG』『すべてのファイル』の4種類だから…

<フィルタ文字列の指定>

param.filter = new Array();
param.filter[0] = "ビットマップファイル(*.bmp)|*.bmp";
param.filter[1] = "JPEGイメージ(*.jpg;*.jpeg)|*.jpg;*.jpeg";
param.filter[2] = "PNGイメージ(*.png)|*.png";
param.filter[3] = "すべてのファイル(*.*)|*.*";

…っていうふうに、1つの要素に1種類を指定するの。
ビットマップファイル(*.bmp)』っていう部分は表示されてるからわかるけど、 『|*.bmp』っていう部分はどういう意味なの?
ファイルの種類が「ビットマップファイル」になってる時には、拡張子が bmp のファイルだけ表示する、っていう意味。
上のダイアログボックスでもそうなってるでしょ。
あ、ほんとだ。全部 bmp ファイルになってるね。
ちなみに2種類以上の拡張子を表示したい時は『*.jpg;*.jpeg』みたいに『;』で区切ればいいんだ。
あと、全部のファイルを表示したい場合は『*.*』ね。
なるほどね。
あと、initialDir には最初に表示するフォルダの名前を指定するんだ。
System.exePath っていうのは?
System.exePathSystem クラスの読み取り専用プロパティで、 吉里吉里本体、つまり krkr.eXe のあるフォルダの名前(パス)を取得できるんだ。
じゃあ、吉里吉里本体と同じフォルダにあるファイルが最初に表示されるってこと?
そういうこと。
で、最後の save は「名前を付けて保存」ダイアログボックスを表示する時は true にして、 「ファイルを開く」ダイアログボックスを表示する時は false にするんだ。
false になってるってことは、「ファイルを開く」ダイアログボックスが表示されるってことだね。
うん。
あと他にも指定できる要素があるんだけど、今回は特に指定する必要がなかったから省略してるよ。
詳しくは吉里吉里2リファレンスの『Storages クラス』の『selectFile』の項目を参照してね。
はーい。
それと、selectFile メソッドの戻り値は、 ファイルが選択されて「開く」ボタンが押されると true、キャンセルボタンが押されると false になるよ。
ってことは…このスクリプトを実行してファイルを選択すると、fileName にファイル名が保存されて、 その後 name プロパティを通して fileName に保存されてるファイル名が表示されるんだよね?
うん、そのとーり。
それじゃ、ここからが今回の本題ね。
えっ、今までのって前置きだったの?
うん、ここまで全部前置き。
……
そ、そうなんだ…
まぁまぁ、今回はそんなに難しい内容じゃないから。
う〜ん…それにしても長い前置きだったね。
新しいことをやるとどうしても説明が長くなっちゃうからね〜。
まぁそれは確かにそうかもね…
それで、本題って?
まず、SimpleFileSelector クラスを継承して、テキストファイルを選択するためのクラスを作るところからね。
あ、そういえば最初に今回も継承の続きって言ってたよね…
というワケで、これが SimpleFileSelector クラスを継承して作った TextFileSelector クラス。

SimpleFileSelector クラスを継承してテキストファイルを選択するようにしたクラス:TextFileSelector クラス>

class TextFileSelector extends SimpleFileSelector
{
    // コンストラクタ
    function TextFileSelector()
    {
        super.SimpleFileSelector();  // スーパークラスのコンストラクタを呼び出します
    }

    // デストラクタ
    function finalize()
    {
        super.finalize();  // スーパークラスのデストラクタを呼び出します
    }

    // 辞書配列の中身を変えるためにオーバーライドしています
    function getParams()
    {
        // スーパークラスの getParams メソッドを呼び出して辞書配列を取得します
        var params = super.getParams();

        // テキストファイル用にフィルタ文字列を変更しています
        params.filter = "テキストファイル(*.txt)|*.txt";

        return params;
    }
}

TextFileSelector クラスにも getParams メソッドがあるね。
うん、そこがポイント。
こんなふうにサブクラスでスーパークラスと同じ名前のメソッドやプロパティを定義することをオーバーライドっていうんだ。
オーバーライドねぇ…
あ、じゃあ、スーパークラスの getParams メソッドはどうなっちゃうの?
サブクラスからは見えなくなるね。
それって、サブクラスからは呼び出せなくなっちゃうってこと?
ううん。そういうわけじゃないよ。
前回も言ったように、super キーワードを使うと、 スーパークラスのメソッドが使えるから…
super.getParams();』で呼び出せるってことだよね?
よく見たらスクリプトにもそう書いてあるし。
ん、そゆこと。
あと、デストラクタは finalize っていう名前のメソッドって決まってるから、 継承すると必ずオーバーライドすることになるよね。
あ、そっか。確かにそうなるね。
じゃあ、本題の説明はこれで終わりね。
えっ、もう終わりなの?
うん。オーバーライドについては大体解ったでしょ?
まぁ…確かにだいたい解ったかな。
あ、もしかして今回新しいクラスを作ったのって、オーバーライドの説明だけだとすぐ終わっちゃうからなんじゃ…?
ん〜、まぁそれもあるんだけどね。
ファイルの選択って後で出てくるから、今のうちにやっとこうかと思って。
ファイルの選択ってこの後どこかで使うの?
うん。
アラームを鳴らす機能をつける時に、どのサウンドファイルをアラームとして使うか設定する時にね。
あ、なるほどね〜。
ま、それは次の章になるんだけどね。
じゃあ、TextFileSelector クラスを使ってみよっか。
うん。

TextFileSelector クラスの使用例>

var sel = new TextFileSelector();

if(sel.openFile())
    System.shellExecute("notepad", Storages.getLocalName(sel.name));

invalidate sel;

とりあえず実行して、何かテキストファイルを選んでみて。
あと、今回はスクリプトが結構長くなっちゃったから、必要なスクリプトをファイルにまとめといたよ。
zip 形式にしてあるから、解凍して使ってね。
うん、おっけー。
それじゃ、実行してみるね。

<実行結果>

メモ帳

あっ、メモ帳が起動してテキストファイルの中身が表示された!
ん、これはそういうスクリプト。
shellExecute っていうの、初めて使うメソッドだよね?
もしかしてこれでメモ帳を起動してるの?
うん、そだよ。
shellExecute メソッドは外部プログラムを実行するメソッドなんだ。
第1引数の "notepad" っていうのは?
第1引数には実行したいプログラムの名前を指定するんだ。
Windows のメモ帳は notepad.exe っていうファイル名なんだけど、 ".exe" の部分は省略できるから、"notepad" でメモ帳が起動できるんだ。
へぇ、そんな機能もあるんだ。
あ、じゃあ第2引数に開くファイル名を指定するんだね。
ん〜、厳密には第2引数は開くファイル名ってわけじゃないんだけど、メモ帳の場合は開くファイル名になるね。
その辺を説明するとややこしくなるから、詳しい説明はパスさせてもらうね。
そうなんだ。うん、わかった。
あと、name プロパティに保存されてるファイル名は統一ストレージ名になってるんだけど、 Windows のメモ帳は統一ストレージ名を認識できないから、Windows 用のファイル名に変換してるんだ。
あ、だから getLocalName メソッドを使ってるんだね。
うん、そういうこと。
じゃ、今回はこんなところかな。
今回はメインのオーバーライドと関係ないことを色々やっちゃったけど、オーバーライドは解ったよね?
うん、だいじょぶだよ。
あとファイル選択についても大体解ったよ。
ん、それなら OK。
それじゃ、また次回ね!


前へ | TOP | 次へ