Section 2.4 メンバ変数とメソッド(その2)

メンバ変数とメソッドについてはもうだいたい解ったよね?
うん!
というワケで、今回は §1.20 のスクリプトをベースにして、Clock クラスを作ってみて。
あの4つの関数Clock クラスのメソッドにすればいいの?
ん〜、後々の事を考えると、変えといた方がいい関数もあるね。
どれを変えるの?
えっとね…こんな感じかな。

Clock クラスのメソッド>

<そのまま使う関数> <変更する関数> <追加する関数>

なんか数が増えてるんだけど…
時刻を返すメソッドが欲しかったからちょっと追加してみたんだ。
しかも戻り値が辞書配列ってのもあるし…
あー、辞書配列を返すのは簡単だからだいじょぶだよ。
そうなの?
うん。関数自体もそんなに複雑じゃないしね。
じゃあ次はメンバ変数を決めとこうか。
Clock クラスのメンバ変数はこの4つね。

Clock クラスのメンバ変数>

メンバ変数はわかりやすいね。
でしょ。
じゃあ、後はコンストラクタとデストラクタね。

Clock クラスのコンストラクタとデストラクタ>

これも解るよね?
うん、OK だよ。
それじゃ、まずはコンストラクタとデストラクタから作っていこっか。
これは簡単だね。
じゃ作ってみて。
コンストラクタで alarm_onfalse に初期化して、 デストラクタでは何もしなくていいんだから、こうだよね。

Clock クラスのコンストラクタとデストラクタ>

class Clock
{
    var alarm_hour, alarm_min, alarm_sec;  // アラームを鳴らす時、分、秒
    var alarm_on;  // アラームがセットされていれば真、セットされていなければ偽

    // コンストラクタ
    function Clock()
    {
        // メンバ変数を初期化します
        alarm_on = false;
    }

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

ん、これで OK だね。
じゃあ次は getTime メソッドを作ってみて。
getTime メソッドって、今回追加するメソッドだよね?
そ。現在時刻を辞書配列の形で返すメソッドだよ。
辞書配列を返すのって、どうやってやるの?
こんな感じにすればいいよ。

<辞書配列を返す関数の例>

function getDic()
{
    return %["a" => 1, "b" => 2];  // "a" と "b" を要素に持つ辞書配列を返します
}

var dic = getDic();  // getDic 関数の戻り値を受け取ると dic は辞書配列として使えるようになります

System.inform("dic.a = " + dic.a + ", dic.b = " + dic.b);

%[...] って、§1.15 で辞書配列を初期化する時に使った書き方だよね?
うん。それを return の後に書けば辞書配列を返せるよ。
あと、戻り値を代入した変数は普通に辞書配列として使えるから。
なるほどね。
じゃあ、getTime メソッドは…

getTime メソッド>

// 現在の時刻を返します
function getTime()
{
    var d = new Date();
    var hour = d.getHours();
    var min = d.getMinutes();
    var sec = d.getSeconds();
    return %["hour" => hour, "min" => min, "sec" => sec];
}

これでいいんじゃないかな?
ん、これでもいいんだけど、もっと簡単にこう書けるよ。

getTime メソッド(改)>

// 現在の時刻を返します
function getTime()
{
    var d = new Date();
    return %["hour" => d.getHours(), "min" => d.getMinutes(), "sec" => d.getSeconds()];
}

そっか。Date クラスのメソッドの戻り値を直接辞書配列の要素に代入してもいいんだね。
うん。
じゃ次は setAlarmTime メソッドね。
setAlarmTime メソッドって calculateTime 関数を変更して作るんだよね?
そうそう。calculateTime 関数は値を返してたけど、 setAlarmTime メソッドは値を返さずに、計算結果をメンバ変数にセットするの。
じゃあ、calculateTime 関数の hourminutealarm_houralarm_min に置き換えればいいってこと…?
ん、そうなるね。
秒はどうすればいいの?
秒は現在時刻、つまり getSeconds メソッドの戻り値でいいよ。
あと、アラームがセットされてるかどうかを表す alarm_ontrue にするのを忘れないでね。
うん、わかった。
じゃ、やってみるね。

setAlarmTime メソッド>

// 今から minute 分後にアラームをセットします
// 戻り値はありません
function setAlarmTime(minute)
{
    var d = new Date();
    alarm_hour = d.getHours();
    alarm_min = d.getMinutes() + minute;
    alarm_hour += alarm_min \ 60;
    alarm_min %= 60;  
    alarm_hour %= 24;  
    alarm_sec = d.getSeconds();
    alarm_on = true;
}

こんな感じでどうかな?
んー、せっかく getTime メソッドを作ったわけだから、 現在時刻は getTime メソッドを使って取得するようにしてみよっか。
あ、そっか。
え〜っと、getTime メソッドは現在時刻を辞書配列で返すんだったよね。
戻り値は普通の辞書配列として使えるから…

setAlarmTime メソッド(改)>

// 今から minute 分後にアラームをセットします
// 戻り値はありません
function setAlarmTime(minute)
{
    var time = getTime();
    alarm_hour = time.hour;
    alarm_min = time.min + minute;
    alarm_hour += alarm_min \ 60;
    alarm_min %= 60;  
    alarm_hour %= 24;  
    alarm_sec = time.sec;
    alarm_on = true;
}

これでいいのかな?
うん、OK。
じゃ今度は getAlarmTime メソッドを作ってみて。
getAlarmTime メソッドも getTime メソッドと同じように時刻を辞書配列で返すんだよね?
うん。要素の名前も同じでいいよ。
あとアラームがセットされてない場合は void を返してね。
アラームがセットされてない場合って、alarm_onfalse の場合ってこと?
ん、そう。
わかった。
えっと、今度はメンバ変数の値を辞書配列の要素に代入すればいいんだから…

getAlarmTime メソッド>

// アラームを鳴らす時刻を返します
// アラームがセットされていない場合は void を返します
function getAlarmTime()
{
    if(!alarm_on)
        return void;  // アラームがセットされていないので void を返します

    return %["hour" => alarm_hour, "min" => alarm_min, "sec" => alarm_sec];
}

これでいいんじゃないかな。
ん、完璧だね。
でしょ〜。これはちょっと自信あったんだ。
じゃあ、次は setAlarm メソッドいってみよっか。
setAlarm メソッドって getInput 関数がベースになるんだよね?
うん。
OK が押された場合はアラームをセットするってのと、戻り値が truefalse になるってのが変更点だね。
アラームをセットするのは、さっき作った setAlarmTime メソッドを使えばいいんだよね?
ん、そう。
じゃ、やってみるね。

setAlarm メソッド>

// アラームの時刻を指定するための入力ウィンドウを表示します
// OK ボタンが押された場合はアラームをセットして true を返します
// キャンセルボタンが押された場合は何もせずに false を返します
function setAlarm()
{
    var value;
    while(true)
    {
        // 入力を受け取ります
        value = System.inputString("何分後にアラームを鳴らしますか?""1 以上 1439 以下の数字を入力してください。""");
        if(value === void)
            return false;  // キャンセルされた場合は false を返します

        // 入力された文字列を数値に変換します
        value = toNumber(value);
        if(value !== void)
            break;

        // 入力された値が正しくない場合は、メッセージを表示してもう一度入力を求めます
        System.inform("1 以上 1439 以下の数字を入力してください。""エラー");
    }

    // 正しい値が入力された場合はアラームをセットして true を返します
    setAlarmTime(value);
    return true;
}

これでいいと思うんだけど…どうかな?
うん、ちゃんとできてるよ。ばっちりだね。
やったぁ!
んじゃ最後は cancelAlarm メソッド
これは簡単だよね。
アラームを解除するってことは、alarm_onfalse にすればいいだけなんだよね?
そうそう。
じゃあ…

cancelAlarm メソッド>

// アラームを解除します
function cancelAlarm()
{
    alarm_on = false;
}

これでいいんだよね?
ん、OK。
あとは、isNumber 関数と toNumber 関数をそのまま Clock クラスの定義に入れればいいんだよね?
うん、それで完成だよ。
それじゃ、Clock クラスの定義全体を書いとくね。

Clock クラス>

class Clock
{
    var alarm_hour, alarm_min, alarm_sec;  // アラームを鳴らす時、分、秒
    var alarm_on;  // アラームがセットされていれば真、セットされていなければ偽

    // コンストラクタ
    function Clock()
    {
        // メンバ変数を初期化します
        alarm_on = false;
    }

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

    // 引数が数値(0以上の整数)と見なせれば真、見なせなければ偽を返します
    function isNumber(value)
    {
        var i, ch;
        for(i = 0; i < value.length; i++)
        {
            ch = value.charAt(i);     // i 文字目を取得
            if(ch < "0" || ch > "9")  // ch が数字("0"〜"9")でない → 数値でない
                return false;
        }
        return true;
    }

    // 引数(文字列型)を数値に変換した値を返します
    // ただし、引数が数値と見なせない場合や、範囲外の数値の場合は void を返します
    function toNumber(value)
    {
        // 引数が数値とみなせない場合は void を返します
        if(!isNumber(value))
            return void;

        value = +value;

        // 引数が範囲外の数値の場合は void を返します
        if(value < 1 || value > 1439)
            return void;

        return value;
    }

    // 現在の時刻を返します
    function getTime()
    {
        var d = new Date();
        return %["hour" => d.getHours(), "min" => d.getMinutes(), "sec" => d.getSeconds()];
    }

    // 今から minute 分後にアラームをセットします
    // 戻り値はありません
    function setAlarmTime(minute)
    {
        var time = getTime();
        alarm_hour = time.hour;
        alarm_min = time.min + minute;
        alarm_hour += alarm_min \ 60;
        alarm_min %= 60;  
        alarm_hour %= 24;  
        alarm_sec = time.sec;
        alarm_on = true;
    }

    // アラームを鳴らす時刻を返します
    // アラームがセットされていない場合は void を返します
    function getAlarmTime()
    {
        if(!alarm_on)
            return void;  // アラームがセットされていないので void を返します

        return %["hour" => alarm_hour, "min" => alarm_min, "sec" => alarm_sec];
    }

    // アラームの時刻を指定するための入力ウィンドウを表示します
    // OK ボタンが押された場合はアラームをセットして true を返します
    // キャンセルボタンが押された場合は何もせずに false を返します
    function setAlarm()
    {
        var value;
        while(true)
        {
            // 入力を受け取ります
            value = System.inputString("何分後にアラームを鳴らしますか?""1 以上 1439 以下の数字を入力してください。""");
            if(value === void)
                return false;  // キャンセルされた場合は false を返します

            // 入力された文字列を数値に変換します
            value = toNumber(value);
            if(value !== void)
                break;

            // 入力された値が正しくない場合は、メッセージを表示してもう一度入力を求めます
            System.inform("1 以上 1439 以下の数字を入力してください。""エラー");
        }

        // 正しい値が入力された場合はアラームをセットして true を返します
        setAlarmTime(value);
        return true;
    }

    // アラームを解除します
    function cancelAlarm()
    {
        alarm_on = false;
    }
}

わぁ、Clock クラスってこんなに長かったんだねぇ…
うん、今まで書いてきたスクリプトの中では一番長いよね。
でもまだこれで終わりじゃないよ。今度はオブジェクトを作ってメソッドを実行するスクリプトね。
そっかぁ、まだそれがあったね。
とりあえず、この2つのスクリプトを書いてみて。

  1. getTime メソッドを使って現在時刻を表示

  2. setAlarm メソッドを使ってアラームをセットした後 getAlarmTime メソッドを使ってアラームを鳴らす時刻を表示

うん、わかった。
じゃ、現在時刻を表示する方から書いてみるね。

<現在時刻を表示するスクリプト>

var clock = new Clock();  // オブジェクトを作ります

var time = clock.getTime();  // 現在時刻を取得します

System.inform("今 " + time.hour + " 時 " + time.min + " 分 " + time.sec + " 秒です。");

invalidate clock;  // 要らなくなったので無効化します

ん〜、こんな感じかな。
じゃ実行してみて。
うん。

<実行結果>

表示されたメッセージ「今 22 時 6 分 14 秒です。」

ちゃんと今の時刻が表示されたね。
ん、OK だね。
じゃあ次はアラームをセットする方ね。
はーい!

<アラームをセットして、アラームを鳴らす時刻を表示するスクリプト>

var clock = new Clock();  // オブジェクトを作ります

if(clock.setAlarm())
{
    // アラームがセットされた場合はアラームを鳴らす時刻を取得して表示します
    var time = clock.getAlarmTime();
    System.inform("アラームを鳴らす時刻は " + time.hour + " 時 " + time.min + " 分 " + time.sec + " 秒です。");
}

invalidate clock;  // 要らなくなったので無効化します

こんな感じでどう?
じゃ、実行してみよっか。
うん。
100』って入力して、OK。

<実行結果>

表示されたメッセージ「アラームを鳴らす時刻は 23 時 55 分 51 秒です。」

えっと、今は 2215 分で、 100 分後は…2355 分だから合ってるよね。
ん、これも OK だね。
なんか今回は調子いいね〜。
でしょ〜。
だいぶ解ってきたような気がするんだ〜。
それじゃ、この先もその調子でがんばってね!
うん、りょーかい!
それじゃ、今回はここまで。
また次回ね!


前へ | TOP | 次へ