361 lines
28 KiB
HTML
361 lines
28 KiB
HTML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
|
|
<!-- generated by to_html.pl from class.xml -->
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
<title>クラス</title>
|
|
<meta name="author" content="W.Dee" />
|
|
<meta http-equiv="Content-Style-Type" content="text/css" />
|
|
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
|
<link href="browser.css" type="text/css" rel="stylesheet" title="吉里吉里関連リファレンス用標準スタイル" />
|
|
<link href="mailto:[email protected]" rev="Made" />
|
|
<link href="index.html" target="_top" rel="Start" title="トップページ" />
|
|
</head>
|
|
<body>
|
|
<h1><a id="id47" name="id47">クラス</a>
|
|
</h1><div class="para"><div>
|
|
クラスは、オブジェクトを作成するときの雛形となるものです。クラスに属する変数をメンバ変数、クラスに属する関数をメンバ関数、あるいはメソッドと呼び、クラスに属するプロパティはメンバプロパティと呼びます。<br />
|
|
<br />
|
|
クラスは基本的には以下のようにして宣言します。<br />
|
|
|
|
<br />
|
|
<code class="bq"><a id="id48" name="id48" class="targanchor"><dfn>class</dfn></a> classname<br />
|
|
{<br />
|
|
<span class="comment">// メンバやメンバメソッドやメンバプロパティを記述</span><br />
|
|
<br />
|
|
function classname() <span class="comment">// コンストラクタ</span><br />
|
|
{<br />
|
|
}<br />
|
|
<br />
|
|
function <a id="id49" name="id49" class="targanchor"><dfn>finalize</dfn></a>()<br />
|
|
{<br />
|
|
}<br />
|
|
}<br />
|
|
<br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
クラス名には識別子を指定します。<br />
|
|
<br />
|
|
クラス内には、そのクラスが作成されたときにメンバとなる変数やメソッド、プロパティを記述します。<br />
|
|
<br />
|
|
クラス内には、クラスと同名のメソッドが必ず一つあり、<a id="id50" name="id50" class="targanchor"><dfn>コンストラクタ</dfn></a>と呼ばれます。これは、 <a id="id51" name="id51" class="targanchor"><dfn>new</dfn></a> 演算子を使用してオブジェクトを作成するとき、この関数が new 演算子の引数を伴って呼び出されます。<br />
|
|
<br />
|
|
クラス内には同様に、finalize という特殊なメソッドがあります。これは、オブジェクトが消滅するときに呼ばれるメソッドで、省略可能です。書かなくてもかまいません。<br />
|
|
<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> class test<br />
|
|
{<br />
|
|
function test()<br />
|
|
{<br />
|
|
<span class="comment">// コンストラクタ</span><br />
|
|
<span class="comment">// ここに、オブジェクトが作成されるときに処理する内容を書く</span><br />
|
|
variable = 0;<br />
|
|
}<br />
|
|
<br />
|
|
function finalize()<br />
|
|
{<br />
|
|
<span class="comment">// finalize メソッド</span><br />
|
|
<span class="comment">// ここに、オブジェクトが破棄されるときに処理する内容を書く</span><br />
|
|
}<br />
|
|
<br />
|
|
function method1()<br />
|
|
{<br />
|
|
<span class="comment">// メソッド</span><br />
|
|
System.inform(variable);<br />
|
|
}<br />
|
|
<br />
|
|
var variable; <span class="comment">// メンバ変数</span><br />
|
|
<br />
|
|
property prop <span class="comment">// メンバプロパティ</span><br />
|
|
{<br />
|
|
getter() { return variable; } <br />
|
|
}<br />
|
|
}<br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
クラスに対して instanceof 演算子を "Class" を伴って使用した場合は真になります(上記の例で言うと、test instanceof "Class" は真)。<br />
|
|
</div></div>
|
|
<h1><a id="id52" name="id52">オブジェクトの作成</a>
|
|
</h1><div class="para"><div>
|
|
宣言したクラスのオブジェクトを作成するには new 演算子を使います。<br />
|
|
new 演算子の後には、関数呼び出しと同様に、クラス名と、コンストラクタに渡す引数を指定します。<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> class Test<br />
|
|
{<br />
|
|
var variable1 = getValue(); <span class="comment">// メンバ変数の初期化</span><br />
|
|
<br />
|
|
function Test(arg1, arg2) <span class="comment">// コンストラクタ</span><br />
|
|
{<br />
|
|
<span class="comment">// ここでは new 演算子で指定した引数が arg1 と arg2 にわたっている</span><br />
|
|
}<br />
|
|
}<br />
|
|
<br />
|
|
var newobject = new Test(1, 2); <span class="comment">// 引数に 1, 2 を渡して test クラスのオブジェクトを作成</span><br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
クラスが作成されるときの処理の順番は以下の通りです。<br />
|
|
<br />
|
|
<ol><li>まず空のオブジェクトが作成される</li><li>メソッド、プロパティが登録される</li><li>メンバ変数が作成される ( このとき初期化が必要な変数は初期化される )</li><li>コンストラクタが実行される</li></ol><br /><div class="note"><div class="notehead"><span class="noteheadspan">Note</span></div>
|
|
コンストラクタへの引数がない場合であっても、new 演算子の ( ) を省略することはできません。 JavaScript のように new Test と書くことはできません。new Test( ) と書く必要があります。<br />
|
|
</div><br />
|
|
<br />
|
|
特に、クラスのメソッドやプロパティ内でそのクラスのオブジェクトを作成する場合、あるいはそのクラスのスーパークラスのオブジェクトを作成する場合、以下のようにするとエラーになります。<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> class Test<br />
|
|
{<br />
|
|
function Test() <span class="comment">// コンストラクタ</span><br />
|
|
{<br />
|
|
}<br />
|
|
<br />
|
|
function func()<br />
|
|
{<br />
|
|
return new Test(); <span class="comment">// エラー</span><br />
|
|
}<br />
|
|
}<br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
なぜならば、クラスのメソッドやプロパティ内で Test と単に書くと、クラスである Test よりもそのコンストラクタの Test の方がスコープ的に近いため、コンストラクタの Test 参照されてしまうからです。この場合はこれを避けるために、以下のように明示的に global. を使用する必要があります ( クラスは global に登録されるからです )。<br />
|
|
<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> class Test<br />
|
|
{<br />
|
|
function Test() <span class="comment">// コンストラクタ</span><br />
|
|
{<br />
|
|
}<br />
|
|
<br />
|
|
function func()<br />
|
|
{<br />
|
|
return new global.Test(); <span class="comment">// これならば OK</span><br />
|
|
}<br />
|
|
}<br />
|
|
</code>
|
|
<br />
|
|
|
|
</div></div>
|
|
<h1><a id="id53" name="id53">オブジェクトの無効化</a>
|
|
</h1><div class="para"><div>
|
|
TJS2 では、オブジェクトが削除される際、オブジェクトの<a id="id54" name="id54" class="targanchor"><dfn>無効化</dfn></a>とオブジェクトの削除、という2つの段階を踏みます。<br />
|
|
オブジェクトが無効化されるとき、 finalize メソッドが呼ばれ、そのオブジェクトは無効であるというマークがつけられます。以降のそのオブジェクトへのアクセスはすべて失敗し、例外が発生するようになります。オブジェクトが無効化されているかどうかは <a id="id55" name="id55" class="targanchor"><dfn>isvalid</dfn></a> 演算子で調べることができます。<br />
|
|
<br />
|
|
オブジェクトは <a id="id56" name="id56" class="targanchor"><dfn>invalidate</dfn></a> 演算子で無効化することができます。<br />
|
|
<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> class Test<br />
|
|
{<br />
|
|
var variable;<br />
|
|
<br />
|
|
function Test()<br />
|
|
{<br />
|
|
<span class="comment">// コンストラクタ</span><br />
|
|
variable = new AnotherClass();<br />
|
|
}<br />
|
|
<br />
|
|
function finalize()<br />
|
|
{<br />
|
|
<span class="comment">// finalize メソッドは無効化された時に呼ばれる</span><br />
|
|
invalidate variable;<br />
|
|
}<br />
|
|
}<br />
|
|
<br />
|
|
var object = new Test(); <span class="comment">// オブジェクトを作成</span><br />
|
|
<br />
|
|
(略)<br />
|
|
<br />
|
|
invalidate object; <span class="comment">// オブジェクトを無効化</span><br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
invalidate 演算子を用いなくても、オブジェクトは必要とされなくなった時点で削除されます。このとき、無効化されていなければ、その時点で無効化されます。<br />
|
|
TJS2 ではいつオブジェクトが削除されるかの明確な規定が無く、削除や無効化は「いつでもおこりうる」ことになります。したがって、無効化されてないオブジェクトは削除時に無効化されるため、思わぬ時点で finalize メソッドが呼ばれてしまう可能性があります。これを避けるためにも、オブジェクトを使い終わったら invalidate 演算子で無効化することをおすすめします。<br />
|
|
<br />
|
|
<br /><div class="note"><div class="notehead"><span class="noteheadspan">Note</span></div>
|
|
invalidate 演算子は C++ の delete 演算子に近い働きをします。<br />
|
|
TJS2 の delete 演算子は C++ の delete 演算子と違い、メンバやローカル変数を削除するための演算子です。オブジェクト自体を無効化したり削除したりはしませんが、メンバやローカル変数を削除したことにより結果的にオブジェクトの無効化や削除を引き起こすことはあります。<br />
|
|
</div><br />
|
|
</div></div>
|
|
<h1><a id="id57" name="id57">オブジェクトへのアクセス</a>
|
|
</h1><div class="para"><div>
|
|
作成したオブジェクトのメンバ変数、メソッド、メンバプロパティには、<a id="id58" name="id58" class="targanchor"><dfn>.</dfn></a> (メンバ選択) 演算子 または <a id="id59" name="id59" class="targanchor"><dfn>[ ]</dfn></a> (間接メンバ選択演算子) を用いてアクセスします。<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> var obj=new MyLayer(window,window.prmaryLayer)<br />
|
|
obj.method1(); <span class="comment">// メソッドの呼び出し obj['method1']() でも同じ</span><br />
|
|
obj.num = 3; <span class="comment">// メンバ変数へ代入 obj['num']=3 でも同じ</span><br />
|
|
obj.prop1++; <span class="comment">// メンバプロパティにアクセス obj['prop1']++ でも同じ</span><br />
|
|
</code>
|
|
<br />
|
|
|
|
</div></div>
|
|
<h1><a id="id60" name="id60">クロージャ</a>
|
|
</h1><div class="para"><div>
|
|
作成したオブジェクトのメソッドやメンバプロパティは、そのメンバがどのオブジェクトのメンバであるかの情報を持った状態でオブジェクトに登録されています。<br />
|
|
そのため、メソッドやメンバプロパティをオブジェクト外に持ち出して、それを使用しても、元のオブジェクトに対するアクセスを行うことになります。この機能をクロージャと呼びます。また、アクセス先のオブジェクトを<a id="id61" name="id61" class="targanchor"><dfn>コンテキスト</dfn></a>と呼びます。<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> var obj = new FooBarClass(); <span class="comment">// オブジェクトを作成</span><br />
|
|
obj.method(); <span class="comment">// オブジェクトのメソッドを普通に呼び出す</span><br />
|
|
var objmethod = obj.method; <span class="comment">// オブジェクトのメソッドへの参照を objmethod に代入</span><br />
|
|
objmethod(); <span class="comment">// objmethod を呼び出すが、obj.method() と同じく、obj に対するアクセスとなる</span><br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
<a id="id62" name="id62" class="targanchor"><dfn>incontextof</dfn></a> 演算子は、どのオブジェクトのメンバであるか、の情報を変更し、任意のコンテキスト上でメソッドを実行するための方法を提供します。<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> (objmethod incontextof obj2)(); <span class="comment">// obj2 に対する操作になる</span><br />
|
|
(objmethod incontextof this)(); <span class="comment">// this に対する操作になる</span></code>
|
|
<br />
|
|
|
|
</div></div>
|
|
|
|
<h1><a id="id63" name="id63">継承</a>
|
|
</h1><div class="para"><div>
|
|
キーワード <a id="id64" name="id64" class="targanchor"><dfn>extends</dfn></a> を用いると、クラスを別のクラスから継承させることができます。継承とは、継承元のクラスのメンバを引き継ぐことです。<br />
|
|
継承する元となるクラスのことを<a id="id65" name="id65" class="targanchor"><dfn>スーパークラス</dfn></a>、継承したクラスのことを<a id="id66" name="id66" class="targanchor"><dfn>サブクラス</dfn></a>と呼びます。<br />
|
|
以下のようにしてクラスを宣言します。<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> class Class1 <span class="comment">// スーパークラス</span><br />
|
|
{<br />
|
|
function Class1() <span class="comment">// Class1 コンストラクタ</span><br />
|
|
{<br />
|
|
}<br />
|
|
<br />
|
|
function finalize() <span class="comment">// Class1 finalize</span><br />
|
|
{<br />
|
|
}<br />
|
|
<br />
|
|
function method1() <span class="comment">// method1</span><br />
|
|
{<br />
|
|
}<br />
|
|
}<br />
|
|
<br />
|
|
<br />
|
|
class Class2 extends Class1<br />
|
|
{<br />
|
|
function Class2() <span class="comment">// Class2 コンストラクタ</span><br />
|
|
{<br />
|
|
super.Class1(); <span class="comment">// Class1 コンストラクタを呼ぶ</span><br />
|
|
}<br />
|
|
<br />
|
|
function finalize() <span class="comment">// Class2 finalize</span><br />
|
|
{<br />
|
|
super.finalize();<br />
|
|
}<br />
|
|
}<br />
|
|
<br />
|
|
var obj = new Class2(); <span class="comment">// Class2 オブジェクトを作成</span><br />
|
|
obj.method1(); <span class="comment">// Class2 は Class1 の method1 を継承しているので使用することができる</span><br />
|
|
</code>
|
|
<br />
|
|
|
|
上記の例では、Class2 が Class1 を継承しています。Class2 は Class1 から<a id="id67" name="id67" class="targanchor"><dfn>派生</dfn></a>している、とも言います。<br />
|
|
Class2 のコンストラクタ内では Class1 のコンストラクタを、Class2 の finalize では Class1 の finalize を呼んでいます。<em>サブクラスが、これらのメソッド内でスーパークラスの該当する同メソッドを呼び出さなかった場合の動作は未定義</em> ( というか現バージョンでは呼んだかどうかチェックしていない ) ですので、必ず記述するようにしてください。<br />
|
|
<br />
|
|
サブクラスからスーパークラスを参照するためには、上記の例のようにキーワード <a id="id68" name="id68" class="targanchor"><dfn>super</dfn></a> を使用することができます。このキーワードはサブクラス内でのみ使用可能で、スーパークラスを表すものです。<br />
|
|
<br />
|
|
継承が行われている場合の、new 演算子でのオブジェクトの初期化の順序は以下の通りです。<br />
|
|
<br />
|
|
<ol><li>まず空のオブジェクトが作成される</li><li>メソッド、プロパティが登録される ( スーパークラスから先に、サブクラスに向かって )</li><li>メンバ変数が作成される ( スーパークラスから先に、サブクラスに向かって )</li><li>サブクラスのコンストラクタが呼ばれる</li><li>( サブクラスのコンストラクタ内から ) スーパークラスのコンストラクタが呼ばれる</li></ol></div></div>
|
|
<h1><a id="id69" name="id69">多重継承</a>
|
|
</h1><div class="para"><div>
|
|
extends の後に、スーパークラス名を複数記述すると、多重継承を行わせることができます。<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> class SubClass extends ClassA, ClassB<br />
|
|
{<br />
|
|
function SubClass() <span class="comment">// SubClass コンストラクタ</span><br />
|
|
{<br />
|
|
ClassA(); <span class="comment">// ClassA コンストラクタを呼ぶ</span><br />
|
|
ClassB(); <span class="comment">// ClassB コンストラクタを呼ぶ</span><br />
|
|
}<br />
|
|
<br />
|
|
function finalize() <span class="comment">// Class2 finalize</span><br />
|
|
{<br />
|
|
global.ClassA.finalize();<br />
|
|
global.ClassB.finalize();<br />
|
|
}<br />
|
|
}<br />
|
|
<br />
|
|
</code>
|
|
<br />
|
|
|
|
super キーワードが使えないため、明示的にクラスを指定しなければなりません。例のように スーパークラスのメソッドを呼ぶときに global. をわざわざつけてクラスにアクセスするのは、サブクラス内で単に ClassA と記述すると ClassA のコンストラクタのことを指すからです。クラスそのものは global に登録されるため、global. を用いてクラスにアクセスします。<br />
|
|
<br />
|
|
多重継承が行われている場合の、new 演算子でのオブジェクトの初期化の順序は多重継承を行っていないときのそれと同じすが、スーパークラスのメソッド、プロパティの登録の順番は、extends キーワードの後に書いた順に行われます。継承元のクラス間で同名のメソッドやプロパティがあった場合は、後に書いたほうが優先されます。隠れてしまったメソッドやプロパティには、global.ClassA.hiddenMethod() のように明示的にクラス名を書いてアクセスする事ができます。<br />
|
|
</div></div>
|
|
<h1><a id="id70" name="id70">オーバーライド</a>
|
|
</h1><div class="para"><div>
|
|
サブクラスでスーパークラスのメソッドやメンバプロパティと同名のものを宣言すると、スーパークラスのメソッドを隠すことができます。これをオーバーライドと呼びます。<br />
|
|
上記の説明の中にでてきた finalize メソッドは、スーパークラスの finalize メソッドをオーバーライドしています。<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /> class Class1 <span class="comment">// スーパークラス</span><br />
|
|
{<br />
|
|
function Class1() <span class="comment">// Class1 コンストラクタ</span><br />
|
|
{<br />
|
|
}<br />
|
|
<br />
|
|
function finalize() <span class="comment">// Class1 finalize</span><br />
|
|
{<br />
|
|
}<br />
|
|
<br />
|
|
function method1() <span class="comment">// method1</span><br />
|
|
{<br />
|
|
(略)<br />
|
|
}<br />
|
|
}<br />
|
|
<br />
|
|
<br />
|
|
class Class2 extends Class1<br />
|
|
{<br />
|
|
function Class2() <span class="comment">// Class2 コンストラクタ</span><br />
|
|
{<br />
|
|
super.Class1(); <span class="comment">// Class1 コンストラクタを呼ぶ</span><br />
|
|
}<br />
|
|
<br />
|
|
function finalize() <span class="comment">// Class2 finalize</span><br />
|
|
{<br />
|
|
super.finalize();<br />
|
|
}<br />
|
|
<br />
|
|
function method1() <span class="comment">// Class1.method1 をオーバーライド</span><br />
|
|
{<br />
|
|
(略)<br />
|
|
if(略) return super.method1();<br />
|
|
(略)<br />
|
|
}<br />
|
|
}<br />
|
|
<br />
|
|
var obj = new Class2(); <span class="comment">// Class2 オブジェクトを作成</span><br />
|
|
obj.method1(); <span class="comment">// Class2 の method1 が呼ばれる</span><br />
|
|
</code>
|
|
<br />
|
|
|
|
サブクラスのメソッドやプロパティでは super キーワードを用いてスーパークラスのメソッドやプロパティにアクセスすることができます。<br />
|
|
<br />
|
|
メンバ変数をオーバーライドすることはできません。メンバ変数は一つのオブジェクトに対して登録されるため、サブクラスとスーパークラスで同名のメンバ関数があると
|
|
サブクラスの変数がスーパークラスの変数を上書きしてしまいます。<br />
|
|
</div></div>
|
|
<script type="text/javascript" charset="UTF-8" src="documentid.js" ></script>
|
|
<script type="text/javascript" charset="UTF-8" src="postcontent.js" ></script>
|
|
</body>
|
|
</html>
|