トップへ戻るニュースフォーラムFLASH-ML 過去ログBak@Flaダウンロードよくある質問と答
ログイン
ユーザ名:

パスワード:


パスワード紛失

新規登録
メインメニュー
メイン
   コーダーズルーム【スクリプト系】
     クラス内の変数について
投稿するにはまず登録を

スレッド表示 | 新しいものから 前のトピック | 次のトピック | 下へ
投稿者 スレッド
takiguchi
Åê¹ÆNo.3527
投稿日時: 2004-2-5 7:02
半人前
居住地: 東京
投稿: 38
使用環境:
Win2K,FlashMX2004Pro7.0.1
クラス内の変数について
(2004/2/9 修正・ムダを省きました)
win2000/Flash MX 2004 v7.0.1で
ActionScript 2.0 を使ってOOPの勉強をしています。
OOPの勉強を始めたばかりなのですが、
クラスを作成する時に、ちょっと疑問に思うことがあります。

■プロパティについて
プロパティは、メソッドの外側のクラス内で宣言された変数で、
同一クラスのメソッドやサブクラスからアクセスすることができる。

■メソッド(コンストラクタ関数含む)内で宣言された変数(プロパティではない変数)
メソッド内で宣言された変数(引数含む)は、そのメソッド内でのみ有効で、
メソッドの最後に無効となる。
従って、同一クラスの他のメソッドやサブクラスからアクセスすることができない。

…と私なりに考えているのですが、疑問点は下記の通りです。
(特にマニュアルのローカル変数についての記述を読んで
「う?ん?」と考え込んでしまいました。)

[疑問点]

1.メソッドの引数をvarステートメントを使って宣言する必要はあるのでしょうか?

2.異なるメソッドの引数で同じ名前を使ってもコンフリクトは起こらないのでしょうか?

3.メソッド内で宣言された変数と同じ名前の変数を他のメソッドで宣言しても
コンフリクトは起こらないのでしょうか?

4.クラスのプロパティと同じ名前の変数をメソッドで宣言しても
コンフリクトは起こらないのでしょうか?

5.MovieClip.gotoAndPlayメソッド(引数としてString又はNumber)のようにオーバーロードされた
メソッドを定義する場合、MovieClip.asを参照してみると引数をObjectとしていますが、
クラスの階層構造が良く分からないので理解に苦しんでいます。
StringクラスとNumberクラスはObjectクラスのサブクラスなのかなぁ??
という感じはしてるんですけど…

私なりに以下のような実験をしてみました。

例1)疑問1用の実験
---------------------------------------------------------------------
//MyClass1.as
class MyClass1 {
    function method(param1:String, param2:Number):Void {
        trace("param1:"+param1+", param2:"+param2);
    }
}
---------------------------------------------------------------------
//MyClass2.as
class MyClass2 {
    function method(param1, param2):Void {
        var param1:String;
        var param2:Number;
        trace("param1:"+param1+", param2:"+param2);
    }
}
---------------------------------------------------------------------
//MyClass2a.as
class MyClass2a {
    function method(param1:String, param2:Number):Void{
        var param1:String=new String();
        var param2:Number=new Number();
        trace("param1:"+param1+", param2:"+param2);
    }
}
---------------------------------------------------------------------
//FLAファイル //メインタイムライン:フレーム1
var a:String="test";
var b:Number=100;
var c:MyClass1= new MyClass1();
var d:MyClass2= new MyClass2();
var e:MyClass2a= new MyClass2a();
c.method(a,b); //出力 param1:test, param2:100 //c.method(b,a)はエラー
d.method(a,b); //出力 param1:test, param2:100 //d.method(b,a)はエラーなし
e.method(a,b); //出力 param1:, param2:0 //e.method(b,a)はエラー
d.method(b,a); //出力 param1:100, param2:test
---------------------------------------------------------------------

いつもメソッドを定義する時はMyClass1のやり方で引数を宣言しているのですが、
MyClass2のような記述もOKなのでしょうか?(特にエラーにならないですし…)
それとMyClass1とMyClass2で違いはあるのでしょうか?




例2)疑問2,3,4用の実験
---------------------------------------------------------------------
class MyClass {
    //プロパティ定義
    var param1:String = "unset";
    var param2:Number = 0;
    //コンストラクタ関数
    function MyClass(param1:String, param3:Number) { //var a:MyClass=new MyClass("Hello",100);
        var param2:Number = param3;
        trace(param1+","+param2); //出力 Hellow,100
        trace(this.param1+","+this.param2); //出力 unset,0
    }
    //メソッド定義
    function method1(Void):Void {
        trace(param1+","+param2); //出力 unset,0
    }
    function method2(param1:String, param2:Number):Void { // a.method2("abcd",10);
        trace(param1+","+param2); //出力 abcd,10
        trace(this.param1+","+this.param2); //出力 unset,0
    }
    function method3(Void):Void {
        var param1:String = "ABCD";
        var param2:Number = 20;
        trace(param1+","+param2); //出力 ABCD,20
        trace(this.param1+","+this.param2); //出力 unset,0
    }
}
---------------------------------------------------------------------
//FLAファイル //メインタイムライン:フレーム1
var a:MyClass=new MyClass("Hello",100);
a.method1();
a.method2("abcd",10);
a.method3();
---------------------------------------------------------------------

上記の結果ではメソッド内で宣言された変数は独立していて、
他のメソッドの変数やプロパティとはコンフリクトが起こらないみたいです。

ただし、クラスのプロパティと同じ名前の変数がメソッドで宣言されている場合は、
メソッド内で宣言されている変数が優先される感じです。
ということは、クラスのプロパティと同じ名前の変数をメソッドで宣言すると、
そのメソッドからアクセス不可能なプロパティが存在してしまうことになるのでしょうか?

変数の名前が重複することは避けるべきだとは思いますが…
何分、私には英語力がないので、一つ一つ別の変数名を考えるのが
正直かなりの負担となってます。

コンフリクトが起こらないと保証される局面では、重複した名前の変数を
使って、ちょっとは楽できるかなぁ?と思ってます。

あと、5.オーバーロードのやり方はどうやって調べれば良いか分かりませんでした。

以上のことに関するアドバイスや間違った理解をしている等のご指摘をして頂けると助かります。
野中文雄
Åê¹ÆNo.3529
投稿日時: 2004-2-5 10:42
ちょんまげら
居住地: 東京
投稿: 4531
使用環境:
CS5.5 .6.8 Vista Home Premium (SP1)
Re: クラス内の変数について
ご質問が多岐にわたるので、小分けにしてお答えします。

ActionScript 2.0では、型指定は必須ではありません
引用:
takiguchiさんは書きました:
1.メソッドの引数をvarステートメントを使って宣言する必要はあるのでしょうか?

クラス定義時だけでなく、ムービー内に定義した関数でも同じですので、フレームアクションの例を示します([コーダーズルーム]とはいえ、あまり他のみなさんがヒビってもいけないので)。

関数の引数に型指定してあると、他の型で宣言された値を引数に渡したとき、コンパイルエラーを発生します。
// フレームアクション
function method(param1:String, param2:Number):Void {
	trace("arguments: "+param1+","+param2);
}
// var a:String = "test";  // エラーなし
var a:Number = 200;  // コンパイルエラー
// a = 200;  // エラーなし
var b:Number = 100;
method(a, b);
// method(200, 100);  // コンパイルエラー

ただ、渡す変数が型指定されていないと、素通りです。使えないじゃんと思われたら、型指定しなくても構いません。(^^;
引用:
//MyClass1.as
class MyClass1 {
	function method(param1:String, param2:Number):Void{
// [中略]
//MyClass2.as
class MyClass2 {
	function method(param1, param2):Void{

いつもメソッドを定義する時はMyClass1のやり方で引数を宣言しているのですが、
MyClass2のような記述もOKなのでしょうか?(特にエラーにならないですし…)
それとMyClass1とMyClass2で違いはあるのでしょうか?


----------------
 

野中文雄
Åê¹ÆNo.3530
投稿日時: 2004-2-5 11:05
ちょんまげら
居住地: 東京
投稿: 4531
使用環境:
CS5.5 .6.8 Vista Home Premium (SP1)
Re: クラス内の変数について
関数の引数およびローカル変数は、その関数ブロック内でのみ有効です。関数の処理が終了するとともに、メモリから破棄されます。したがって、他の関数や、関数の外側(クラスのプロパティ宣言やタイムライン変数の宣言)で同一の識別子(名前)を使用しても、コンフリクトは発生しません。
引用:
takiguchiさんは書きました:
2.異なるメソッドの引数で同じ名前を使ってもコンフリクトは起こらないのでしょうか?
3.メソッド内で宣言された変数と同じ名前の変数を他のメソッドで宣言しても
コンフリクトは起こらないのでしょうか?
4.クラスのプロパティと同じ名前の変数をメソッドで宣言しても
コンフリクトは起こらないのでしょうか?

ActionScriptが関数を処理するとき、識別子を「ローカル変数」>「タイムライン変数」または「インスタンスプロパティ」>「グローバル変数」の順に探していきます(これを「スコープチェーン」と呼びます)。そして、合致する値が見つかれば、その先は関知しません。

コンフリクトが避けられる一方で、スコープチェーンのその先の変数の検索が遮断されます。この性質を意図的に使うことを、「隠ぺい」といいます。たとえば、インスタンスのデフォルト値を設定する手法として利用することができます([クラスの作成と使用][訳者註*1]参照。ただし、この動作はJavaやJScript.NETなどの他のオブジェクト指向言語とは異なります)。
引用:
ただし、クラスのプロパティと同じ名前の変数がメソッドで宣言されている場合は、
メソッド内で宣言されている変数が優先される感じです。
ということは、クラスのプロパティと同じ名前の変数をメソッドで宣言すると、
そのメソッドからアクセス不可能なプロパティが存在してしまうことになるのでしょうか?

スコープチェーンの先の変数は、ターゲットを明示的に指定すれば、参照可能です。また、フレームアクションのサンプルを示します。
// フレームアクション
_global.myProperty = "global";
trace(myProperty);  // 出力: global
myProperty = "timeline";
function xTest(_str:String):Void {
	trace(myProperty);  // 出力: timeline
	var myProperty = "local";
	trace(myProperty);  // 出力: local
	trace(this.myProperty);  // 出力: timeline
	trace(_global.myProperty);  // 出力: global
}
xTest();
trace(myProperty);  // 出力: timeline
trace(this.myProperty);  // 出力: timeline
trace(_global.myProperty);  // 出力: global


----------------
 

野中文雄
Åê¹ÆNo.3531
投稿日時: 2004-2-5 11:16
ちょんまげら
居住地: 東京
投稿: 4531
使用環境:
CS5.5 .6.8 Vista Home Premium (SP1)
Re: クラス内の変数について
最後のご質問ですね。(^^;;

Objectクラスは、すべてのクラスに継承されています。クラスやオブジェクトの相関関係は、Katoさんが作成されています(Flash MXのものですが、MX 2004でもとくに変更はないと思います)。
引用:
takiguchiさんは書きました:
5.MovieClip.gotoAndPlayメソッド(引数としてString又はNumber)のようにオーバーロードされた
メソッドを定義する場合、MovieClip.asを参照してみると引数をObjectとしていますが、
クラスの階層構造が良く分からないので理解に苦しんでいます。
StringクラスとNumberクラスはObjectクラスのサブクラスなのかなぁ??
という感じはしてるんですけど…

引数の型に応じて同名の異なるメソッドを定義するいわゆる「オーバーロード」は、ActionScript 2.0では実装されていません。

メソッドはあくまでひとつにして、引数の型により処理を条件分岐するという方法をとらざるをえません。その場合、引数の型はObjectで指定することになるでしょう。
引用:
あと、オーバーロードのやり方はどうやって調べれば良いか分かりませんでした。

ぶっちゃけた話、ActionScript 2.0の厳密な型指定は、SWFに書出す(これを「コンパイル」といっています。コンパイル型言語と異なり、ネイティブコードに変換する訳ではありませんが)ときのみの実装です。簡単にいえば、シンタックスチェックだけの機能です。日本の大学と同じく、入試というチェック後の動作については、管理が及びません。

そして大事なことは、書出されるバイトコード(ActionScriptとネイティブコードの中間コード)自体は、1.0と同値です。


----------------
 

植木友浩
Åê¹ÆNo.3532
投稿日時: 2004-2-5 12:05
案内係
居住地: 東京
投稿: 640
使用環境:
Pro +
.Tiger +
Re: クラス内の変数について
引用:

Fumioさんは書きました:
そして大事なことは、書出されるバイトコード(ActionScriptとネイティブコードの中間コード)自体は、1.0と同値です。


r65以降とFlash Player7にしてしまうと、レジスタ数の増加で、バイトコードは今までとは違ったものになるような話を聞いたんですが。


----------------
Tomohiro Ueki
RSSリーダー公開中
チーム-10kg達成

野中文雄
Åê¹ÆNo.3545
投稿日時: 2004-2-5 18:54
ちょんまげら
居住地: 東京
投稿: 4531
使用環境:
CS5.5 .6.8 Vista Home Premium (SP1)
Re: クラス内の変数について
厳密にいえば、若干の違いはあるようです。たとえば、ActionScript 1.0では、クラスのprototypenew継承するのがスタンダードですが、2.0のextends__proto__プロパティを使っているようです。しかし、1.0で記述できるという点は、変わらないと思います。

レジスタによる処理の最適化は、Flash Playerのバージョンによるものでしょう。1.0であっても、6.0r65用に最適化すれば、レジスタの恩恵は受けられます。
引用:
tomohiroさんは書きました:
r65以降とFlash Player7にしてしまうと、レジスタ数の増加で、バイトコードは今までとは違ったものになるような話を聞いたんですが。


----------------
 

takiguchi
Åê¹ÆNo.3548
投稿日時: 2004-2-5 20:09
半人前
居住地: 東京
投稿: 38
使用環境:
Win2K,FlashMX2004Pro7.0.1
Re: クラス内の変数について
(2004/2/9 修正)
■コンフリクトについて
分かりやすい説明で感激しています。
コンフリクトに関してはそれほどナーバスにならなくても
良いような気がしてきました。

■スコープチェーンについて
thisのスコープに戸惑うことがありますが、なんとなく分かってきました。
クラスのメソッド内でthisを使用すると、そのクラスのインスタンスを参照する!?
という考えで正しいでしょうか?
メソッド(関数)内の変数(ローカル変数)とプロパティ(タイムライン変数)を区別するために、
メソッド内でプロパティを参照する時は、thisを付ける癖を付けておいた方が良い
との結論に達しましたけど…間違っていたら訂正してください。

■ActionScript 2.0の厳密な型指定について
ところで「var」って何者?ってことで以下のような実験です。
例1)
------------------------------------------------------------------------------------------------------------------------
//FLAファイル
//メインタイムライン:フレーム1
//インライン初期化なし型宣言
var a:String;
trace("a type:"+typeof(a)); //出力 a type:undefined

a=this; //String型で宣言し、MovieClip型で初期化
trace("a type:"+typeof(a)); //出力 a type:movieclip

//コードヒントの確認…aはMovieClip型なのにString型のコードヒントが表示される
a.
------------------------------------------------------------------------------------------------------------------------

変なことが起こってしまいました。
指定した型とは異なる型で初期化が出来てしまいました。
インライン初期化しないとダメなのでしょうか?
'var'を使った宣言でインライン初期化しない場合は、
宣言された変数の型は'undefined'となり、型がまだ定まっていないようです。

それから、インライン初期化についてちょっと質問が…
紹介していただいたFN0310006「クラスの作成と使用」
「インスタンスごとにプロパティを設定したい場合には、
その値をコンストラクタ関数内で設定する必要があります」
との記載がありますが、AS1.0の経験がないために'prototype'プロパティと
staticキーワードの区別がなかなかつきません。
コンストラクタ関数内で初期化しないプロパティはstatic的なものになるような
感じがしちゃうんですけど…でもちょっと違う気も…

質問ばかりで恐縮ですが、宜しくお願い致します。

■オーバーロードについて
---------------------------------------------------------------------
//MovieClip.as内
function gotoAndStop(frame:Object):Void; // frame can be String or Number
---------------------------------------------------------------------

Objectクラスは、すべてのクラスに継承されてるのであれば、
「引数の型にObjectを指定する」=「引数の型を指定しない(なんでもあり)」
という意味に考えても差し支えないのでしょうか?…とちょっと手抜き思考

function gotoAndStop(frame):Void; // frame can be String or Number

引数の型をある範囲で限定できないのが、ちょっと不便な気がしますけど、
オーバーロードが実装されていないだけに仕方ないです…
野中文雄
Åê¹ÆNo.3556
投稿日時: 2004-2-6 9:59
ちょんまげら
居住地: 東京
投稿: 4531
使用環境:
CS5.5 .6.8 Vista Home Premium (SP1)
Re: クラス内の変数について
まず、型指定とtypeof演算子が返すデータ型とは、無関係です。前者は、自己申告です。後者は、データの実質を評価するものの、判別できるデータ型はかぎられています。

前者の型指定がしてあっても後者のデータ型は未定義undefinedということはあり、逆に型指定されていなくてもデータ型は調べられます。
引用:
takiguchiさんは書きました:
ところで「var」って何者?ってことで以下のような実験です。
//メインタイムライン:フレーム1
//インライン初期化なし型宣言
// [中略]
var a:String;
trace("a type:"+typeof(a));	//出力	a type:undefined

a=this;	//String型で宣言し、MovieClip型で初期化
trace("a type:"+typeof(a));	//出力	a type:movieclip

変なことが起こってしまいました。
指定した型とは異なる型で初期化が出来てしまいました。
インライン初期化しないとダメなのでしょうか?
'var'を使った宣言でインライン初期化しない場合は、
宣言された変数の型は'undefined'となり、型がまだ定まっていないようです。

自己申告ということは、申告しなければ型がないと認識されます。
// フレームアクション
var my_str:String;
nNumber = 10;
my_str = nNumber;  // エラーなし

つまり、アメリカの大学を卒業したとか余計な自己申告をしなければ、コンパイルエラーは発生しないということです。(^^;

そして、フレームアクションにおけるタイムラインthisは、実は型指定されていません。
// フレームアクション
var my_str:String = "this";
this = my_str;  // エラーなし
trace(this);


----------------
 

takiguchi
Åê¹ÆNo.3558
投稿日時: 2004-2-6 11:00
半人前
居住地: 東京
投稿: 38
使用環境:
Win2K,FlashMX2004Pro7.0.1
Re: クラス内の変数について
野中さん、ありがとうございます。

------------------------------------------------------------------------------------------------------------------------
var a:Boolean;
//a=100; //エラー
b=100; //b:型指定なし
a=b; //エラーなし
------------------------------------------------------------------------------------------------------------------------

型指定した変数に対して、それと違った型の値を代入すると、
エラーになりました。
thisは型なしだからエラーにならなかったんですね。(^^;;

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
以前の投稿で間違った記述をした部分がありましたので削除しました。
発言が二転三転してしまい、申し訳ありません。
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

また、慌てて投稿すると間違ってしまいそうなので、時間を掛けて整理していきたいと思います。(^^;;
野中文雄
Åê¹ÆNo.3563
投稿日時: 2004-2-6 12:45
ちょんまげら
居住地: 東京
投稿: 4531
使用環境:
CS5.5 .6.8 Vista Home Premium (SP1)
Re: クラス内の変数について
クラスのprototypeに設定されたプロパティは、インスタンスが使用するものです。その点で、クラス自身のプロパティとして操作されるクラスメンバとは異なります。

prototypeに設定されるインスタンスメンバは、最近話題になったTV電話で対応して薬を販売する薬剤師さんのようなものです。お客さんが薬を買いにくると、TV電話を通じてそのお店の薬剤師さんとして対応します。複数の店舗を担当するとしても、個々のお客さんに対してはそのお店のスタッフとして当たるのです。

これに対してクラスメンバは、本社勤務の薬剤師さんです。担当するのは、あくまで本社(クラス)の仕事です。仕事場はTV電話の薬剤師さんと同じビルの別フロアかもしれません。しかし、仕事を依頼するには、本社に対して本社の業務としてお願いしなければなりません。
引用:
takiguchiさんは書きました:
、AS1.0の経験がないために'prototype'プロパティと
staticキーワードの区別がなかなかつきません。
コンストラクタ関数内で初期化しないプロパティはstatic的なものになるような
感じがしちゃうんですけど…でもちょっと違う気も…(^^;;


----------------
 

(1) 2 3 »
スレッド表示 | 新しいものから 前のトピック | 次のトピック | トップ

投稿するにはまず登録を
 
Copyright (C) 2003 FLASH-japan. All rights reserved.
Powered by Xoops