Perlの継承について

このQ&Aのポイント
  • クラスSubclassはクラスBaseclassを継承し、myfunc1をオーバーライドしています。
  • Subclassのmyfunc1を呼び出す方法はありますか?Baseclassのmyfunc1を呼び出す方法を教えてください。
  • Baseclassのmyfunc2内の$self->myfunc1(...)の記載をBaseclass::myfunc1($self, ...)に変更することで、Baseclassのmyfunc1を呼び出せる可能性があります。
回答を見る
  • ベストアンサー

Perlの継承について

Perlの継承について (1) クラス Subclass (baseclassを継承) myfunc1 (2) クラス Baseclass myfunc1 myfunc2 (myfunc2内でmyfuncを呼び出している) (3) SubclassとBaseclassのmyfunc1は、引数が異なる。 上記のようにクラスSubclassとクラスBaseclassがあり、SubclassはBaseclassを継承しています。 ここで、SubclassではBaseclassのmyfunc1をオーバーライドしています。 1: my $obj = Subclass->new(); 2: $obj->myfunc2(); とすると、2にて、Subclassにて実装したmyfunc1が呼び出されます。これを、Baseclassのmyfunc1を呼び出させる方法はないでしょうか? (Baseclassはその他のクラスからも継承されておりいじりたくない。 しかし、SubclassはBaseclassを継承したうえでmyfunc1をオーバーライドしたい。) Baseclassのmyfunc2内の  $self->myfunc1(...) という記載を、  Baseclass::myfunc1($self, ...) という記載にしてしまえば動きそうな気もするのですが、何かつっこみがあればお願いします。

  • Perl
  • 回答数2
  • ありがとう数9

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

そういうことなら仕様です。 {   package BaseClass;   sub func1 { print "BaseClass::func1", $/ }   sub func2 {     my $self = shift;     print "BaseClass::func1", $/;     print '$self = ', ref($self), $/;     func1($self);   } } {   package SubClass;   use base qw(BaseClass);   sub new {     my $class = shift;     bless {}, $class;   }   sub func1 { print "SubClass::func1", $/ } } my $sub = SubClass->new(); $sub->func2(); 上のコードを実行すると BaseClass::func1 $self = SubClass BaseClass::func1 となります。 データとblessされたパッケージ名がSubClassなので、SubClassから関数を探します。ただし、上の例で書いてあるとおりBaseClassの関数を呼ぶ場合は、func1($self)でOKです。 無理にやろうとすれば、一旦blessされたパッケージ名をBaseClassに変えてからfunc2()を呼ぶという方法もあります。わかりづらいので、避けたほうがよいでしょう。 my $sub = SubClass->new(); my $base = bless $sub, 'BaseClass'; $base->func2(); $sub = bless $base, 'SubClass';

nshoes
質問者

お礼

おそくなりすいません。回答ありがとうございます。参考にさせてもらいます。

その他の回答 (1)

回答No.1

Baseclass::myfunc1($self, ...)でもできますが、普通はSUPERを使います。 空白を全角にして書いていることに注意 {   package BaseClass;   sub func1 {print "BaseClass::func1", $/} } {   package SubClass;   our @ISA = qw(BaseClass);   sub func1 {print "SubClass::func1", $/}   sub func2 {     my ($self) = @_;     print "SubClass::func2", $/;     $self->SUPER::func1();   } } SubClass->func2();

nshoes
質問者

お礼

ご回答ありがとうございます。 SubclassからBaseclassの関数を呼び出す際はSUPERを使用するという事は理解しています。ありがとうございます。 今回は、 1. Subclassのインスタンスを生成 2. SubclassのインスタンスからBaseclassにて実装されているmyfunc2を実行 3. myfunc2内にて記載されるmyfunc1が呼び出される 4. myfunc1はBaseclassで実装されるものを呼び出してほしいが、Subclassでオーバーライドしたものが呼び出される となっており、上記4にて困っております。 コード 1. my $obj = Subclass->new() 2. $obj->myfunc2() 3. $self->myfunc1() #←これはBaseclass内で、myfunc2内に記載されているコード 本来、親クラスから呼び出されたならば、親クラスのmyfunc2が呼び出されるべきだと思うのですが、perlの継承の仕様上しょうがないのかな(?)と思っております。 何かあればツッコミお願いします。

関連するQ&A

  • PHPのクラス継承において質問

    class SuperClass{ public function getSuperClassName (){ //操作中のオブジェクトのクラス名を取得する print get_class($this); print "<br />"; print __CLASS__; } } class SubClass extends SuperClass{ public function getSubClassName (){ //操作中のオブジェクトのクラス名を取得する print get_class($this); print "<br />"; print __CLASS__; } $obj = new SubClass(); print "<br />"; $obj -> getSuperClassName(); print "<br />"; $obj -> getSubClassName(); 上記のようなコードがあった場合、 出力結果は SubClass SuperClass //継承しているにもかかわらず、SuperClassという文字列が返る。 SubClass SubClass と上記のようになります この結果に一点疑問があるのですが、親クラスのメソッドは子クラスに継承されるんですよね? であれば親クラスの public function getSuperClassName (){ //操作中のオブジェクトのクラス名を取得する print get_class($this); print "<br />"; print __CLASS__; } の箇所の print __CLASS__; の記述箇所はSubClassとでなければいけないような気がします。 しかし結果はSuperClassとでますが、このメソッドは子クラスに継承されていないのですか? publicなら継承されるとマニュアルにかいてありましたが、どうなっているのでしょうか よろしくご教授御願い致します。

    • ベストアンサー
    • PHP
  • perlのクラスについて

    perlでクラスを作成しています。その際、コンストラクタnewで無名配列を定義して、funcメソッドで、この無名配列に値をいれるにはどうすればよいでしょうか? sub new { my $class = shift; my $self->array = []; bless($self, $class); return $self; } sub func { my $self = shift; $self->arrayに配列のデータを入れる。 }

    • ベストアンサー
    • Perl
  • 継承・実装の関係で悩んでいます。

    継承・実装の関係について悩んでいます。 ここでは、アクセス制御を考えずに、インスタンスかstaticかabstract(ここではabstract final staticやabstract classのこと)の違いで、どう継承するのか考えています。 // 継承 はメソッドのオーバーライドのことを考えます。(オーバーロードは考えない) クラスAからクラスBでオーバーライドしたメソッドは、 クラスCでさらにオーバーライドできるのでしょうか? クラスCが クラスBのクラスAからオーバーライドしたメソッド をクラスBのメソッドとして見たときに、オーバーライドすることは可能なのでしょうか? クラスA │ インスタンスフィールドA │ staticフィールドA │ │ クラスA() { } │ │ インスタンスメソッドA () { } │ staticメソッドB() { } ↓ クラスB extends クラスA │ インスタンスフィールドA // 継承 │ インスタンスフィールドB │ staticフィールドB │ │ サブクラス1() { } // コンストラクタは継承しない、super()で呼び出す │ │ インスタンスメソッドA () { } // 継承 │ │ インスタンスメソッドB () { } │ staticメソッドB () { } ↓ クラスC extends クラスB implements インタフェースD, ... ↑ インスタンスフィールドA // クラスBのフィールドを継承 │ インスタンスフィールドB // クラスBのフィールドを継承 │ インスタンスフィールドC │ staticフィールドC │ │ サブクラス2() { } │ │ インスタンスメソッドA () { } // クラスBのメソッドを継承 │ インスタンスメソッドB () { } // クラスBのメソッドを継承 │ インスタンスメソッドD () { } // インタフェースDのメソッドを実装 │ インスタンスメソッドE () { } // インタフェースDのメソッドを実装 │ │ │ インスタンスメソッドC () { } │ staticメソッドC() { } │ interface インタフェースD extends インタフェースE ↑ │ staticフィールドD // public static final │ │ インスタンスメソッドD() { } // public abstract │ インスタンスメソッドE() { } // 継承 │ interface インタフェースE staticフィールドE // public static final インスタンスメソッドE() { } // public abstract

    • ベストアンサー
    • Java
  • picturebox の 継承クラス の ドラッグ

    ご存知のかた教えて頂けないでしょうか? picturebox の 継承クラス を ドラッグできるようにしたいのですが、 継承した picturebox を NEW したクラスから、 AddHandler pBox.MouseMove, AddressOf PBox_MouseMove では出来るのですが、 継承した pictureBox のメソッドをオーバーライドしてドラッグを行いたいのですが、どのようにすればよいのでしょうか? 出来るのでしょうか? 大変申し訳ありません。よろしくお願いします。

  • 継承について(長文です)

    いつもお世話になっています。現在、継承についての練習問題を解いているのですがわからないことがあるので質問させていただきます。 問題は、「自己紹介メソッド(抽象メソッド)を持つIntroduceクラスを作成し、そのクラスを継承してFistsNameクラス、FullNameクラス、IncludeAgeクラスを作成しなさい。三つのサブクラスのインスタンスを混合して配列に保持し自己紹介をしなさい」というものです。 それぞれのクラスはコマンドライン引数で名字(引数一つ)だけ、フルネーム(引数二つ)、フルネームと年齢(引数三つ)と3種類の引数を入力することによって適切なメソッドが呼び出されるということです。(わかりにくい文章ですいません。例えばヤマダと入力すればFirstNameクラスの自己紹介メソッドが呼び出されてヤマダと表示させたいのです)引数をサブクラスに渡さないと行けませんが、まずコンストラクタで引数をサブクラスに渡す場合は引数を一つ(もしくは二つ)しか指定しなかったときはフルネームとフルネーム+年齢のクラスでコンパイルエラー(ArrayIndexOutOfBoundsException)が出ます(これは理解することが出来ます)次にメソッドで渡す場合はシグネチャが異なるのでオーバーライドされずこちらもコンパイルエラーとなります。この他に引数をサブクラスに渡す方法はあるのでしょうか? わかりにくい文章になってしまいましたが、要するに三つのサブクラスをインスタンス化しその後、引数の個数により適切なサブクラスのメソッドが呼び出され引数を連結して表示させたいのです。このようなことは実現できないのでしょうか?if節によって引数の個数で場合分けなどをしないといけないのでしょうか?質問文がわかりにくければ補足させていただきます。よろしくお願いします。

    • ベストアンサー
    • Java
  • オブジェクト指向プログラミング

    Perlのクラス定義の例題なんですが、わからないところがあります。 ファイルCapFile.pm package CapFile; sub new{ my $class = shift; my $path = shift; return(bless { ':path' => $path }, $class); } sub read { my $obj = shift; my $path = $obj->{':path'}; ..... ファイルcap-test #!/usr/bin/perl use CapFile; $cap = new CapFile ('/etc/termcap'); $cap->read(); ... サブルーチンreadにある my $path = $obj->{':path'}; なんですが、呼び出し側では引数がないのですが、$objには何が入っているんでしょうか。 そして$pathには何が入るんでしょうか。

    • ベストアンサー
    • Perl
  • C++の継承と呼び出しについて

    C++について COMとMediaFoundationについて勉強中ですが、継承とオーバーライド の部分で混乱してしまったので、アドバイスをお願いします。 IUnknownクラスは、三つの純粋仮想関数を持っていて、 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)=0; virtual ULONG STDMETHODCALLTYPE AddRef(void)=0; virtual ULONG STDMETHODCALLTYPE Release(void)=0; の三つがあることがわかりました。 そのIUnknownクラスを継承したIMFAsyncCallback、 IMFAsyncCallbackをさらに継承したCPlayerクラスがあります。 CPlayerクラスの中でCPlayer::QueryInterfaceの定義・処理が記述されています。 ここで、ほかのCPlayerクラスの関数内で IUnknownのインスタンス->QueryInterface(引数) ; で呼び出された場合、 CPlayer::QueryInterfaceには飛ばないのでしょうか? 何度ブレークポイントを張ってもきていないので、 いったいどこで処理が行われているか不思議で仕方ないです。 というかIUnknownのインスタンスが作れていることすら疑問です。。。 よろしくお願いします。

  • PHPでの継承について

    PHPの継承についての質問です。 PHPではクラスを継承する場合 スーパークラスのpublicとprotectedなメンバを継承すると いいます。 継承とは、スーパークラスで定義したメンバが サブクラスで定義されたことと同義である。 という前提で質問します。 ひょっとしたらこの前提も微妙に間違っているかもしれません。 以下の用なコードがあるとします。 <?php class AClass { //サブクラスへ継承されるスーパークラスのメソッド public function superClassPublicMethod(){ //【1】 $this-> subClassPrivateMethod(); } } class BClass extends AClass{ public function subClassPublicMethod(){//【2】 $this->subClassPrivateMethod(); } //継承したスーパークラスで定義されているメソッドからコールするサブクラスで定義したメソッド private function subClassPrivateMethod(){ //【3】 print __CLASS__; } } $obj = new BClass(); //サブクラスで定義した public なメソッドを実行 $obj->subClassPublicMethod(); //【4】 //スーパークラスから継承したpublic なメソッドを実行 $obj-> superClassPublicMethod();//【5】 ?> コレを実行すると【4】はきちんとBClassという結果が返ってきます。 ところがその下の【5】を実行すると Fatal error: Call to private method BClass::subClassPrivateMethod() from context 'AClass' in /usr/local/apache/htdocs/ext06.php on line 9 という実行時エラーが返ってきます。これを読むと、AClassのコンテキスト内ではBClassのprivateなメンバは コールできませんよ。というエラーですね。そもそもAClassのコンテキストということは、これはAClass内で実行されているということですよね? ここで、スーパークラスからこのpublicなメソッドは継承しているはずなのになぜ、サブクラスのBCLass内ではなくスーパークラスのAClass内という エラーが返っているのでしょうか? 継承とは、サブクラスで定義したと同義ではなく、スーパークラスまで内部的にアップキャスト?してコールしにいっているのでしょうか? 詳しい方ご教授ください。 よろしく御願いします。

    • ベストアンサー
    • PHP
  • 継承したクラスを、継承元のクラス型の引数に渡すとどうなるのでしょうか?

    継承したクラスを、継承元のクラス型の引数に渡すとどうなるのでしょうか? 以下のようなケースで、 #include "stdio.h" using namespace std; // baseクラス class base { private:  int m_nII;  int m_nJJ;  int m_nKK; public:  base(int i,int j,int k){ m_nII=i; m_nJJ=j; m_nKK=k; }  int GetSum(){ return (m_nII+m_nJJ+m_nKK); } }; // base 継承クラス class hoge : public base { public:  hoge() : base(1,2,3){} }; void func(base* obj){ // baseクラスを引数に取る関数  printf("sum is %d\n", obj->GetSum()); } // main int main(){  hoge objHoge;  func((base*)&objHoge); // <-キャストして渡す  return 0; } として、一応、gccでコンパイルは通り、実行結果も期待通りだったのですが、 このやり方で問題は無いのでしょうか? (たとえば継承先のクラスが独自のメンバを持っていたりなどした場合、期待した結果にならないとか・・) よろしくお願いします。

  • C#の継承関係。

    すこし、疑問におもい質問いたします。 以下のようなコードなのですが using System; using System.Windows.Forms; public class MainClass{ public static void Main (){ Test01 obj01 , obj02; Test02 obj03 , obj04; obj01= new Test01(); obj01.method01(); obj03 = new Test02(); obj03.method02(); try{ obj02 = (Test01)obj03;(1) //obj02.methodp();(2) obj04 = (Test02)obj01;(3) }catch(Exception e){ MessageBox.Show(e.Message); } } } public class Test01{ public void method01(){ MessageBox.Show("スーパークラスメソッド"); } private void methodp (){ MessageBox.Show("スーパークラスプライベートメソッド"); } } public class Test02 : Test01{ public void method02(){ MessageBox.Show("サブクラスメソッド"); } } まず(1)の箇所ですが、これはTest02というTest01のクラスを継承したサブクラスを Test01という親クラスにキャストしてます。 これは、問題なく動いているようです。 ただ、その下の(2)の箇所でキャストしたインスタンスから親クラスのプライベートメソッドにアクセスしようとしたらコンパイル時にエラーとなりました。 サブクラスを親クラスにしても親クラスのプライベートメソッドって使えないのでしょうか?であれば親クラスへのキャストって何のためにあるのでしょうか? 次に(3)の箇所ですが、これはTest01という親クラスをTest02という子クラスにキャストしようとしていますが、どうも、親クラスから子クラスへキャストできないといいう例外が 発生するようです。 これはなぜなのでしょうか? 以上の点でご教授いただけませんでしょうか? よろしくお願いします。

専門家に質問してみよう