« C4D C.O.F.F.E.E. クラスを使うには…_01 | トップページ | C4D C.O.F.F.E.E. クラスを使うには…_03 »

C4D C.O.F.F.E.E. クラスを使うには…_02

クラスの継承/派生…?

C4D C.O.F.F.E.E.のBaseDocumentやPolygonObject/SplineObject、Matrix等もクラスなわけだけど…

PolygonObjectやSplineObjectはPointObjectからの派生クラスでサブクラス、であり…
PointObjectはPolygonObjectやSplineObjectの親クラスであり、基本クラス、スーパークラスであり…

派生クラスは、基本クラスを継承し、基本クラスの機能(メンバ)を使うことができるわけだね。

SplineObjectクラスやPolygonObjectクラスの基本クラスは、PointObjectクラスであり…
PointObjectクラスの基本クラスは、BaseObjectクラスで、その基本クラスは、BaseList4Dクラス。さらにその基本クラスは、BaseList2Dクラス。

だから、SplineObjectクラスやPolygonObjectクラスでもBaseList2Dクラスで定義されたGetNext()メンバ関数で次のオブジェクトを取得する事が可能なわけだ…

BaseList2D/BaseList4Dは、リストを処理する機能を持ち…(階層を持たない単純リストと選択状態等)(階層構造のリスト)
BaseObject以降は3Dオブジェクトを処理する機能を持たせてあります。
C4Dで読み込まれたシーンファイルや、マテリアル、タグ、レンダリング設定等もリスト構造で管理するので、BaseList2Dから派生されていますね。

では、自分でもクラスを派生させ継承してみよう。

/*
クラスの継承
2009.7.29
*/


class test_A//test_Aクラスの定義
{
  public:
    var a;
}

class test_B:test_A//test_Aクラスを継承したtest_Bクラスの定義
{
  public:
    var b;
}

main(doc , op)
{
  var testclass_A = new(test_A);
  var testclass_B = new(test_B);
}

サブクラスのメンバの名前は、スーパークラスと重ならないように…
意味があるので…今直ぐに知りたい方は、オーバーライドでweb検索してください。
似た言葉にオーバーロードがありますが…C.O.F.F.E.E.では?

では、実行…
いきなり実行かい?
このままでは、エラーが出るのだ。

[FAIL] Script 'xxxx' Line 16 Pos 2 : [super()] in constructor expected

super()…?
何だ?

スーパークラスのコンストラクタ関連だね…

では、両方ともコンストラクタを…

/*
クラスの継承
2009.7.29
*/


class test_A//test_Aクラスの定義
{
  public:
    var a;
    test_A(val);
}

test_A::test_A(val)
{
  a = val;
}


class test_B:test_A//test_Aクラスを継承したtest_Bクラスの定義
{
  public:
    var b;
    test_B(val);
}

test_B::test_B(val)
{
  b = val;
  super(val / 2);//スーパークラスのコンストラクタを呼び出す。
}


main(doc , op)
{
  var testclass_A = new(test_A , 10);
  var testclass_B = new(test_B , 100);

  println("A->a : " , testclass_A->a);
  println("B->a : " , testclass_B->a);
  println("B->b : " , testclass_B->b);
}

A->a : 10
B->a : 50
B->b : 100

問題なく実行されました。

test_Bクラスのコンストラクタ内で、super()でスーパークラス(親クラス)のコンストラクタに引数を渡して呼び出しています。

super()はスーパークラスのコンストラクタを呼び出します。

スーパークラスとサブクラスの両方にコンストラクタを付けましたが、
スーパークラスのコンストラクタが無くてもエラーは起こりません。

/*
クラスの継承
2009.7.29
*/


class test_A//test_Aクラスの定義
{
  public:
    var a;
}


class test_B:test_A//test_Aクラスを継承したtest_Bクラスの定義
{
  public:
    var b;
    test_B(val);
}

test_B::test_B(val)
{
  b = val;
  super();//スーパークラスのコンストラクタを呼び出す。
}


main(doc , op)
{
  var testclass_A = new(test_A);
  var testclass_B = new(test_B , 100);

  println("A->a : " , testclass_A->a);
  println("B->a : " , testclass_B->a);
  println("B->b : " , testclass_B->b);
}

A->a : nil
B->a : nil
B->b : 100

その代わり、スーパークラスのメンバ変数は初期化をしていないのでnilになります。
もちろん、スーパークラスから継承したメンバ変数もサブクラスでは初期化されません。

いやいや、サブクラスはスーパークラスを継承しているのだから、サブクラスのコンストラクタで継承したメンバ変数aの初期化をすれば…

/*
クラスの継承
2009.7.29
*/


class test_A//test_Aクラスの定義
{
  public:
    var a;
}


class test_B:test_A//test_Aクラスを継承したtest_Bクラスの定義
{
  public:
    var b;
    test_B(val);
}

test_B::test_B(val)
{
  a = val;
  b = val;
  super();//スーパークラスのコンストラクタを呼び出す。
}


main(doc , op)
{
  var testclass_A = new(test_A);
  var testclass_B = new(test_B , 100);

  println("A->a : " , testclass_A->a);
  println("B->a : " , testclass_B->a);
  println("B->b : " , testclass_B->b);
}

A->a : nil
B->a : 100
B->b : 100

問題なく終了し、エラーは起きません。

では、スーパークラスと同じ名前のメンバをサブクラスで使うと…オーバーライド

/*
クラスの継承
2009.7.29
*/


class test_A//test_Aクラスの定義
{
  public:
    func_1();
    func_2();
}

test_A::func_1()
{
  println("test_A::func_1()");
}

test_A::func_2()
{
  println("test_A::func_2()");
}


class test_B:test_A//test_Aクラスを継承したtest_Bクラスの定義
{
  public:
    test_B();
    func_2();//スーパークラスのメンバと同じ名前の関数
    func_3();
}

test_B::test_B()
{
  super();//スーパークラスのコンストラクタを呼び出す。
}

test_B::func_2()//スーパークラスのメンバと同じ名前の関数
{
  println("test_B::func_2()");
}

test_B::func_3()
{
  println("test_B::func_3()");
}



main(doc , op)
{
  var testclass_A = new(test_A);
  var testclass_B = new(test_B);

  println("testclass_A->func_1()");
  testclass_A->func_1();
  println(" ");

  println("testclass_A->func_2()");
  testclass_A->func_2();
  println(" ");

  println("testclass_B->func_1()");
  testclass_B->func_1();//スーパークラスから継承した関数
  println(" ");

  println("testclass_B->func_2()");
  testclass_B->func_2();//スーパークラスのメンバと同じ名前のメンバ
  println(" ");

  println("testclass_B->func_3()");
  testclass_B->func_3();
  println(" ");
}

testclass_A->func_1()
test_A::func_1()

testclass_A->func_2()
test_A::func_2()

testclass_B->func_1()
test_A::func_1()

testclass_B->func_2()
test_B::func_2()

testclass_B->func_3()
test_B::func_3()

わかりづらいけど…

test_Bクラスを割り当てたtestclass_Bからfunc_2()を呼び出すと…
test_Aクラスのfunc_2()ではなく、test_Bクラスのfunc_2()が呼び出されます。

test_Aクラスのfunc_2()は、test_Bクラスのfunc_2()で上書きされてしまいます。

次に続く…

|

« C4D C.O.F.F.E.E. クラスを使うには…_01 | トップページ | C4D C.O.F.F.E.E. クラスを使うには…_03 »