Strings of Life

PHP/Phalcon/MySQL/JavaScript/RegExp/Ruby/Perl/ActionScript

タグ:ActionScript

インスタンスメソッドとインスタンス変数の継承における関係について学んできた。次に、コンストラクターメソッドに移る。

コンストラクターメソッドは、クラスのインスタンスをセットアップするメソッドを呼び、そのオブジェクトに必要な変数を作成する。

クラスを継承した際には、サブクラスは独自のコンストラクターメソッドを定義できる。サブクラスのコンストラクターメソッドは、サブクラスに関連するセットアップと、サブクラスで必要な変数の定義を行い、スーパークラスのコンストラクターメソッドも実行する。

サブクラスのコンストラクターメソッドを定義する場合には、スーパークラスのコンストラクターをsuperキーワードで呼び出す必要がある。さらに、スーパークラスのコンストラクターメソッドは、インスタンス変数又はインスタンスメソッドへのアクセスよりも先に呼ばなければならない。もし、このような呼び出しがされなかった場合、コンパイラーは引数無しでスーパークラスのコンストラクターを自動的に呼び出す。最後に、superはコンストラクターメソッドの中で1回しか使えない。

インスタンス変数又はインスタンスメソッドにアクセスした後でのsuperの使用を禁止することには、以下のメリットがある。
  • 初期化が完了していないオブジェクトのメソッドが呼び出されるのを防ぐ
  • 初期化が完了していないオブジェクトの変数へのアクセスを防ぐ
  • スーパークラスへのコンストラクターへの変数の代入が、サブクラスのコンストラクターへの変数の代入を上書きしないようにする
super()と、super.methodName()の違いに注意。super()はスーパークラスのコンストラクターメソッドの呼び出しで、サブクラスのコンストラクター内で1回だけしか使えない。一方、super.methodName()は、サブクラスのどこでも、何回でも使える。

superを使って、スーパークラスのコンストラクターメソッドを呼び出してみる。
例:
public class A {
    public function A() {

    }
}

public class B extends A {
    // サブクラスのコンストラクター
    public function B () {
        // スーパークラスのコンストラクターメソッドを呼び出し
        super();
    }
}
今日の進捗:2823→2891/20168

サブクラスがインスタンスメソッドをオーバーライドした時、スーパークラスのバージョンのメソッドは失われていない。super演算子を使うことで、サブクラスのインスタンスからアクセスできるようになっている。
publiic class Rectangle {
    protected var w = 0;
    protected var h = 0;

    public function setSize (newW, newH) {
        w = newW;
        h = newH;
    }
}

public class Square extends Rectangle {
    override public function setSize (newW, newH) {
        if (newW == newH) {
            // スーパークラスのsetSize()をサブクラスから呼び出し
            super.setSize(newW, newH);
        }
    }
}
オーバーライドによって、スーパークラスのメソッドの振る舞いを無効化することもできる。サブクラスで、親クラスのメソッドをオーバーライドした上で、オーバーライドメソッドの中身を空にしておけばよい。


今日の進捗:2787→2810/20168

<余談>

PHPでサブクラスからスーパークラスのメソッドを呼び出す際は、parentキーワードを使う。上記コード例なら、parent::setSize()となる。

ここまで、継承について、再利用(サブクラスがスーパークラスのメソッド及び変数を利用すること)及び拡張(サブクラスが独自のメソッド及び変数を定義すること)を学んだ。

次に、再定義に移る。再定義とは、サブクラスがスーパークラスで定義されたものの別バージョンを提供することである。

(再利用、拡張、再定義は、相互に排他的な関係ではないことに注意。サブクラスは3つの技術を全て使うこともできる)

再定義によって、既存のクラスを、特定の目的にそって、拡張したり、強化したり、無効化したりすることができる。メソッドを再定義することを「オーバーライド(overriding)」と呼ぶ。

ActionScript3.0では、インスタンスメソッドのオーバーライドは可能だが、インスタンス変数・静的変数・静的メソッドのオーバーライドはできない。

スーパークラスのインスタンスメソッドをオーバーライドするには、サブクラスの中で同名のインスタンスメソッドを定義し、overrideキーワードをメソッド定義の前に置く。
例:
public class A {
    public function m () {
        trace("A's m() was called");
    }
}

public class B extends A {
    override public function m () {
        trace("B's m() was called");
    }
}
この例では、Aのメソッドm()を、Aを継承するBの中でオーバーライドしている。

オーバーライドが成功するのは、オーバーライドするメソッドが、オーバーライドされるメソッドと、以下の4点で同じになっている場合だけである。
(1) 名前
(2) アクセスコントロール修飾子
(3) 引数の数
(4) 返り値のタイプ


今日の進捗:2735→2787/20168

インスタンスメソッドとインスタンス変数とは異なり、サブクラスはスーパークラスの静的メソッド・静的変数を継承しない。静的メソッドをサブクラスから呼んだ場合、エラーが発生する。

例:
public class A {
    public static function s () {
        trace("a.s() was called");
    }
}

public class B extends A {
    public function B () {
        B.s(); // エラー:A.s()への無効なアクセス
    }
}
しかし、AかBのいずれかの中で定義されている静的メソッド・静的変数は、A.s()ではなく、クラス名抜きのs()と書けば、呼び出すことができる。とはいえ、静的メソッド・静的変数の呼び出し時にクラス名を含んでおくのが賢明である。クラス名が含まれていれば、そのメソッド・変数の出処が明らかだからだ。


今日の進捗:2715→2724/20168

オブジェクト指向プログラミングにおいて、継承(inheritance)は2つ以上のクラスの形式的な関係を指す。継承によって、あるクラスが他のクラスの変数やメソッドを借りてくる。実用的・技術的な意味では、継承は単にあるクラスが他のクラスのコードを使えるようにするだけである。

しかし、継承という用語には、再利用以上の意味合いがある。継承は、技術的な道具である以上に知的な道具なのである。継承によって、クラスに特有の機能をもたせると同時に、クラスの見た目と振る舞いを他のクラスに似せることもできる。

継承の例:
public class A {
    public var v = 10;

    public function m () {
        trace("Method m() was called");
    }
}

public class B extends A{
    // インスタンス変数もメソッドも無いクラス(Aを継承)
}
継承するには、クラス定義の際にextendsキーワードを用いる。上のコードでは、クラスBがクラスAを継承している。ここで、クラスBをインスタンス化すると、Bを通してAのインスタンス変数やメソッドを呼ぶことができる。

Bのような他のクラスを継承したクラス(サブクラス)は、Aのような継承元のクラス(スーパークラス)で使用できる機能を備えた上位機能(スーパーセット)である。サブクラスは、スーパークラスの機能を備え、さらに独自の機能を持つ。

ここで、クラスBに独自のメソッドを付け足してみる。
public class B extends A{
    public function n () {
        trace("Method n() was called");
    }
}
クラスBは、クラスAの特殊化と呼ばれる。クラスBはクラスAの機能を基本とし、さらに独自の機能を必要に応じて拡張する。2つのクラスの継承関係において、クラスAのような拡張されるクラスを基本クラス(又は祖先クラス)、クラスBのような拡張するクラスを派生クラス(又は子孫クラス)と呼ぶ。

継承では、2つ以上のクラスを含むこともできる。例えば、クラスBを拡張するクラスCを定義すれば、クラスCはクラスBの機能に加え、クラスAの機能も利用することができる。また、スーパークラスは、サブクラスをいくつでも持つことができる。

クラスの継承関係は図で表すことができる。例えば、UML(Unified Modeling Language)を用いてクラスの関係を図式化したりする。


今日の進捗:2554→2715/20168

このページのトップヘ