Movatterモバイル変換


[0]ホーム

URL:


gihyo.jpサイトのロゴ

ActionScript 3.0で始めるオブジェクト指向スクリプティング

第21回プロパティのようにアクセスするメソッド - get/setアクセサメソッド

記事の内容 2.5分

前回の第20回はクラスMyTimerに修正を加えて、public属性のメソッドgetElapsedTime()がMyTimerInfoインスタンスを返すようにした(前回のサンプルファイルは、2ページからダウンロードできる⁠⁠。MyTimerInfoクラスには時分秒ミリ秒をそれぞれ納めるint型のインスタンスプロパティが宣言され、数値でなければ設定できない図1⁠。これらのプロパティを、もっときめ細かく管理できないだろうか。これが今回のテーマである。

図1 int型のプロパティに文字列を設定するとコンパイルエラーになる
図1 int型のプロパティに文字列を設定するとコンパイルエラーになる

プロパティを設定するメソッドの定義

たとえば、MyTimerInfoインスタンスのsecondsプロパティに、整数150を代入してみよう。データ型は正しいので、そのまま150が設定される図2⁠。しかし、時間は60秒につき1分繰上がるのだから、できればminutesプロパティに120秒分の2分が加算され、secondsプロパティは30になってほしい。

図2 60秒以上の値をプロパティsecondsに設定してもminutesに繰上がらない
図2 60秒以上の値をプロパティsecondsに設定してもminutesに繰上がらない

プロパティsecondsの値をminutesに繰上げるには、設定のためのメソッドをMyTimerInfoクラスに用意することが考えられる。secondsプロパティを設定するメソッドは、クラス MyTimerInfo前回のスクリプト2にたとえばsetSeconds()としてつぎのように定義すればよい(他のプロパティは一旦脇に置く⁠⁠。

// ActionScript 3.0クラス定義ファイル: MyTimerInfo.aspackage {  public class MyTimerInfo {    public var milliseconds:int;    public var seconds:int;    public var minutes:int;    public var hours:int;    public function MyTimerInfo(nMilliseconds:Number=0) {      setTime(nMilliseconds);    }public function setSeconds(nSeconds:Number) {   // 追加      setTime(nSeconds*1000);    }    private function setTime(nTime:Number):void {      milliseconds = nTime % 1000;      nTime = Math.floor(nTime / 1000);      seconds = nTime % 60;      nTime = Math.floor(nTime / 60);      minutes = nTime % 60;      hours = Math.floor(nTime / 60);    }  }}

MyTimerInfoインスタンス(oElapsedTime)に対して、このsetSeconds()により設定値の秒数を渡せば、60秒ごとに1分がminutesプロパティに繰上がる。たとえば、setSeconds()メソッドの引数に150秒を渡せば、プロパティminutesに2分が、secondsに30秒が設定される図3⁠。

図3 プロパティsecondsに設定した値は60秒ごとに1分がminutesに繰上がる
図3 プロパティsecondsに設定した値は60秒ごとに1分がminutesに繰上がる

get/setアクセサメソッド

前項『プロパティを設定するメソッドの定義』に述べたとおり、メソッドを定義すればプロパティに対して単にデータ型の指定だけでなく、値の範囲を限定したり、他のプロパティの値と関連づけることができる。しかし、値を設定するという操作は、プロパティの方が端的でわかりやすい。ActionScript 3.0には、プロパティと同じアクセスの仕方で呼出せる特別なメソッドがある。それがgetおよびsetアクセサメソッドだ。

getおよびsetアクセサメソッドは、メソッドにgetおよびset定義キーワードを添えて、以下のように同じメソッド名で定義する。アクセサメソッドにはpublic属性を指定しつつ、内部的に用いるプロパティはprivateとするのが基本だ。

【get/setアクセサメソッドの定義】
private var プロパティ:データ型;public function get アクセサメソッド():データ型 {  return プロパティ;}public function set アクセサメソッド(引数:データ型):void {  プロパティ = 引数;}

getとsetのアクセサメソッドには、プロパティと同じようにアクセスできる。つまり、MyTimerInfoクラスに秒数のprivateプロパティを_secondsで宣言し、getおよびsetアクセサメソッドをsecondsとして以下のように定義し直す(ここでも他のプロパティは一旦脇に置く)と、秒数のプロパティがsecondsであるかのようにアクセスできる図4⁠。

// ActionScript 3.0クラス定義ファイル: MyTimerInfo.aspackage {  public class MyTimerInfo {    public var milliseconds:int;private var_seconds:int;    public var minutes:int;    public var hours:int;    public function MyTimerInfo(nMilliseconds:Number=0) {      setTime(nMilliseconds);    }public functiongetseconds():int {      return_seconds;    }public functionsetseconds(nSeconds:int) {      setTime(nSeconds*1000);    }    private function setTime(nTime:Number):void {      milliseconds = nTime% 1000;      nTime = Math.floor(nTime / 1000);_seconds= nTime% 60;      nTime = Math.floor(nTime / 60);      minutes = nTime% 60;      hours = Math.floor(nTime / 60);    }  }}
図4 アクセサメソッドsecondsにはプロパティのようにアクセスできる
図4 アクセサメソッドsecondsにはプロパティのようにアクセスできる

それでは、改めてクラスMyTimerInfoにget/setアクセサメソッドを定義したい。前回のスクリプト2とは異なり、実際のインスタンスプロパティはprivate属性で指定するので、タイムラインから直接アクセスされることはない。代わりに、get/setアクセサメソッドがプロパティの役割を果たす。すると、実際のプロパティが時分秒ミリ秒の値をそれぞれもつ必要はない。

したがって、privateのインスタンスプロパティは総ミリ秒数のみを保持することとして、時分秒ミリ秒の値はアクセサメソッドの方で分ければよい[1]⁠。そこで、つぎのスクリプト1のように総ミリ秒数のprivateプロパティはtotalMillisecondsとして宣言し、hours、minutes、seconds、millisecondsはアクセサメソッドとして定義した。

スクリプト1 クラスMyTimerInfoにget/setアクセサメソッドを定義
// ActionScript 3.0クラス定義ファイル: MyTimerInfo.aspackage {  public class MyTimerInfo {private vartotalMilliseconds:Number;    public function MyTimerInfo(nMilliseconds:Number=0) {      totalMilliseconds = nMilliseconds;    }public functiongetmilliseconds():int {      var nMilliseconds:int = totalMilliseconds%1000;      return nMilliseconds;    }public functiongetseconds():int {      var nSeconds:int = Math.floor(totalMilliseconds/1000)%60;      return nSeconds;    }public functiongetminutes():int {      var nMinutes:int = Math.floor(totalMilliseconds/1000/60)%60;      return nMinutes;    }public functiongethours():int {      var nHours:int = Math.floor(totalMilliseconds/1000/60/60);      return nHours;    }public functionsetmilliseconds(nMilliseconds:int):void {      setTime(hours, minutes, seconds, nMilliseconds);    }public functionsetseconds(nSeconds:int):void {      setTime(hours, minutes, nSeconds, milliseconds);    }public functionsetminutes(nMinutes:int):void {      setTime(hours, nMinutes, seconds, milliseconds);    }public functionsethours(nHours:int):void {      setTime(nHours, minutes, seconds, milliseconds);    }    public functionsetTime(nHours:int=0, nMinutes:int=0, nSeconds:int=0, nMilliseconds:int=0):void {      nMinutes = nHours*60+nMinutes;      nSeconds = nMinutes*60+nSeconds;      nMilliseconds = nSeconds*1000+nMilliseconds;      totalMilliseconds = nMilliseconds;    }  }}

この仕様変更にともない、setTime()は時分秒ミリ秒をそれぞれ引数として受取るメソッドに定義し直し、総ミリ秒数のprivateプロパティtotalMillisecondsを設定することとした。各メソッドの処理内容は、前回までの説明で理解できよう。なお、setTime()メソッドはpublic属性にしたので、タイムラインから呼出して、時分秒ミリ秒をまとめて設定することも可能だ。

アクセサメソッドsecondsは、タイムラインからたとえばつぎのようなフレームアクションで試すことができる図5⁠。

// タイムライン: メイン// フレームアクションvar myObject:MyTimer = new MyTimer();var oElapsedTime:MyTimerInfo = myObject.getElapsedTime();oElapsedTime.seconds = 150;   // 150秒を設定trace(oElapsedTime.minutes, oElapsedTime.seconds);oElapsedTime.seconds -= 50;   // 50秒を差引くtrace(oElapsedTime.minutes, oElapsedTime.seconds);
図5 アクセサメソッドでプロパティ値を変更する
図5 アクセサメソッドでプロパティ値を変更する

これでクラス定義の基本は、ひととおり解説した。次回からはお題を変えて、MovieClipシンボルにクラスを設定してみたい。

[1]時分秒ミリ秒の各値に素早くアクセスする処理が頻繁かつ大量にあるようなときは、各値をそれぞれ別のプロパティとして保持した方が有利な場合もありえる。

今回解説した次のサンプルファイルがダウンロードできます。

同じ記事グループをもっと見る

おすすめ記事

記事・ニュース一覧


    [8]ページ先頭

    ©2009-2025 Movatter.jp