[Obj-c]元クラスからサブクラスのメソッド

このQ&Aのポイント
  • [Obj-c]元クラスからサブクラスのメソッドについて質問です。
  • ClassAとClassB1には同名のメソッドがありますが、ClassAのインスタンスにClassB1のインスタンスをセットすると、なぜClassB1のメソッドが呼ばれるのか疑問です。
  • また継承しているとはいえ、型が違うものを参照渡しできる理由もわかりません。どういう機能を言うのか教えてください。
回答を見る
  • ベストアンサー

[Obj-c]元クラスからサブクラスのメソッド

Objective-Cの勉強をしています。 ClassAは元クラス(スーパークラス)です、 ClassB1、B2はClassAを継承(サブクラス)しています。 ClassAとClassB1にはiMethodというメソッドが存在します。 最下部にソースと実行結果があります。 ●そこで質問なのですが、  ClassAのインスタンスにClassB1のインスタンスをセットすると、  同じ名前のメソッドがあるだけでなぜClassB1のメソッドが呼ばれるのでしょうか?  (下記ソースの[bangai iMethod]; の部分です。)  ClassB1のインスタンスを渡すとClassAのインスタンスが  ClassB1のメソッドを使用できる理由がわかりません、  継承しているとはいえ型が違うものを参照渡しできる理由も今ひとつわからないです。  またこれはどういう機能を言うのでしょうか?  (例えば ポリモーフィズム、動的バインディングなど) ★ソース ------------------------------------------------------------------------------ #import <Foundation/Foundation.h> // ClassA @interface ClassA : NSObject { } @end @implementation ClassA -(void) iMethod { NSLog(@"スーパークラスのインスタンスメソッドです。\n"); return; } @end // ClassB1 @interface ClassB1 : ClassA @end @implementation ClassB1 -(void) iMethod { NSLog(@"サブクラスのインスタンスメソッドです。\n"); return; } @end // ClassB2 @interface ClassB2 : ClassA @end @implementation ClassB2 @end int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... ClassB1 *instance_B1 = [[ClassB1 alloc]init]; ClassB2 *instance_B2 = [[ClassB2 alloc]init]; [instance_B1 iMethod]; [instance_B2 iMethod]; // 親には子のクラスが入れられる ClassA *bangai = instance_B1; [bangai iMethod]; } return 0; } ------------------------------------------------------------------------------ ★実行結果 サブクラスのインスタンスメソッドです。 スーパークラスのインスタンスメソッドです。 サブクラスのインスタンスメソッドです。

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

  • ベストアンサー
  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.2

実装、というかアーキについてはとりあえず参考URLでも読んでみてください。 これはC++の話ですが、Objective-Cでもそう違いはないと思いますので。

参考URL:
http://www.kab-studio.biz/Programing/PragmaTwice/Main/365.html
Gyustab
質問者

お礼

ご回答ありがとうございます。 ご指定いただいたリンク先にてアーキテクトを学ばせていただきます。 Objective-cは結構なんでもできてしまうのでこういった事を学びたいと思っています。

その他の回答 (1)

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.1

どーでもよくないので予め突っ込んでおきますが、このコード上に「ClassAのインスタンス」は存在しません。 ClassA *bangaiはあくまでただの「ClassA *型の変数」です。 なぜ子クラスのメソッドが実行されるかについてはポリモーフィズム(多態性)の仕様上そうなるように作られているからだ、としか言いようがありません。

Gyustab
質問者

お礼

>どーでもよくないので予め突っ込んでおきますが、このコード上に「ClassAのインスタンス」は存在しません。  ご指摘ありがとうございます、一昨日ようやくわかりました  allocされていないのでClassAのインスタンスはは存在しませんね  ClassA *bangai はポインタ(アドレス番地)の役割しか果たしていないです。 >なぜ子クラスのメソッドが実行されるかについてはポリモーフィズム(多態性)の仕様上そうなるように作られているからだ、 >としか言いようがありません。  はい、そうなんですが  なぜClassA型のアドレス(ポインタ)からClassBのインスタンスメソッドが呼べるのかがわからず  メモリアドレス上に存在するのはClassBのインスタンスなのですが、  ClassA型のアドレス(ポインタ)がClassBのメソッドの関数ポインタ(この考え方が違うかも)の  場所がわかるのかがわかりません  アーキテクチャを知っておいた方が良いのではないかと思っています。

関連するQ&A

  • (クラス名.this.メソッド)って・・・?

    次のようなクラスで public class ClassA {   public static void main(String[]args)   {     new ClassA(); /* 構築A */   }   public ClassA()   {     new ClassI();   }   public class ClassI()   {     ClassA.this.MethodA(); /* 命令A */   }   public void MethodA()   {     System.out.println("HELLO");   } } この命令Aの部分の (クラス名.this.メソッド)というアクセス方法がよくわかりません とりあえす(ClassA.this)が構築Aの部分で生成された インスタンスではないかとおもうのですがそれで正しいのでしょうか? また インナークラスはインナークラスの定義されているクラス以外から インスタンスを生成できないのでしょうか? つまり次のクラスを追加して public class ClassB {   public ClassB()   {     new ClassA.ClassI(); /* 構築B */   } } ここの構築Bのように(この場合はダメの様ですが)他のクラスから 構築することです もし仮にできるとしたら そのときの命令Aの(ClassA.this)は一体なんの インスタンスを指すのでしょうか 急ぎのプログラムを作っているので たいへん不躾ですが、なるべく早くお答えをお願いします

    • ベストアンサー
    • Java
  • 同一クラスインスタンス名で別クラスのインスタンス作成方法(C++)

    下記ソース(Java)の処理をするような、C++の実装方法を教えていただきたいです。 【処理内容】 クラスBのインスタンスを保持しており、クラスBのインスタンス名と同一であるクラスAのインスタンス生成 ClassA A_Instance = (ClassA)Class.forName(B_instance.name).newInstance(); 要はクラスインスタンスの名前の求め方がわからないのです。それさえわかれば、newしてクラスポインタを返すメソッドを用意すれば何とかなると考えていますが。 ※C++のAPI一覧はどこにあるのだろうか・・・

  • objective-c のインスタンスについて教えていただきたいのですが

    初心者なのですみません。 ご存知の方教えていただきたいのですが、 例えばaインスタンスがbクラスをインスタンス化して bインスタンスがcクラスをインスタンス化して aインスタンスがcクラスをインスタンス化しないで bインスタンスがインスタンス化したcインスタンスに メソッド送信のようなことが したいのですがうまくいきません。 どのようにすればよいですか? よろしくお願いします (aインスタンスがcクラスをインスタンス化した場合、bインスタンスがcクラスをインスタンス化したものと同じもの(アドレスが同じ?)なものなのでしょうか?違いますよね?ようするにストレージクラスやNSDataなどインスタンスの中のデータを複数のインスタンスから取り出したいのです) 面倒でスミマセン。 以下は確認のために簡易的に作ったものです。 文字数多すぎなのでinterfaceは省きました #import "Aobject.h" #import "Bobject.h" #import "Cobject.h" @implementation Aobject - (IBAction)callb:(id)sender { id Bobj = [[Bobject alloc]init]; [Bobj make]; [Cobj log]; //ここでエラーが出ます(`Cobj' undeclared (first use in this function) (Each undeclared identifier is reported only once for each function it appears in.)) } @end //-------------------------------------- #import "Bobject.h" #import "Cobject.h" @implementation Bobject - (void)make { id cobj = [[Cobject alloc]init]; } @end //-------------------------------------- #import "Cobject.h" @implementation Cobject - (void)log { NSLog(@"ok"); } @end

    • ベストアンサー
    • Mac
  • 親クラスのフリをした子クラスの使い方を教えて下さい

    以前、QNo.3479089でお世話になった者です。類似というか、続きの質問です。 ClassAを継承するClassBがあり、条件によって、ClassAまたはClassBをインスタンス化して使います。 (ClassBは、ClassAのメソッドの一部をオーバーライドして、ClassB固有のメソッドも追加しています) ClassA* pObj = NULL; if( ある条件 ) {   pObj = new ClassA(); } else( その他の条件 ) {   pObj = new ClassB(); } pObj->common_method(); これが常套手段と伺ったのですが、ClassBがインスタンス化された場合、ClassB固有のメソッドmethodBを呼び出そうとすると、「ClassAにはmethodBが存在しない」といったようなコンパイルエラーが出ます。 pObj->methodB(); // ここで、エラー それで、エラーを解消するために、「その他の条件」の時に、dynamic_castを使ってみました。 if( その他の条件 ) {   ClassB* pObj2 = dynamic_cast<ClassB*>( pObj );   pObj2->methodB(); } 上記でコンパイルエラーは解消したのですが、なにか、非常にめんどくさいです。 また、ClassAのフリをした実体ClassBを使っているのだから、オーバーライドしているメソッドもdynamic_castをしないと呼び出されないような気がします。 結局、親のフリした子クラスを作成する場合、こんなにめんどくさいことをしないといけないのでしょうか? それともこのやり方はおかしいですか? この場合、どういうふうにするものなのか、教えて下さい。よろしくお願いします。

  • Xcodeのクラスについてお聞きします。

    何らかのクラスをつくり、ViewControllerからクラスを生成して そのクラス(以下TestClass)のメソッドにアクセスします。 TestClassのメソッドから呼び出し元のViewControllerの変数若しくはメソッドに アクセスすることはできるのでしょうか? 例) @interface ViewController : UIViewController{ UIlabel *label; //TestClassから書き込みたい } @end @implementation ViewController -(void)viewDidLoad{ TestClass *class = [[TestClass alloc] init]; [class labelWrite];//クラス呼び出し } - (void)hoge{ //TestClassからここにアクセスしたい //処理 } @end @interface TestClass : NSObject @end @implementation TestClass - (void)labelWrite{ //ここからViewControllerのlabelに書き込みたい //もしくはViewControllerのhogeメソッドにアクセスしたい } @end

  • C# クラスのインスタンスについて

    クラス(ClassA)を作成した後に別のクラス(ClassB)内でClassAインスタンスを作成したとします。 このインスタンスをさらに別のクラス(ClassC)で使用したいと思うの ですが可能なんでしょうか? 要するに1つのインスタンスを他で使いまわすような事ができないの かなって思っています。 自分で調べると「Singletonパターン」という方法があるようですが 他の方法もあれば知ってみたいと思っています。 ※環境はWinXP、VS2005 C# です。 以上ですが、よろしくお願いいたします。

  • スーパークラスからサブクラスのメソッドを使おうとする、以下のプログラム

    スーパークラスからサブクラスのメソッドを使おうとする、以下のプログラムでつまずいています。 Aを継承したB、Cクラスのインスタンスを作成し、スーパークラスであるA型の配列asにまとめます。 それからループでas[i]にはいっている各インスタンスのメソッドを使いたいのですが、 スーパークラスAにmethod()がないためコンパイルできません、Aにmethod()を作るとA.method()が実行されます。 BとCを同じ配列に保存し、かつそれぞれのmethod()を実行したい場合どのようにしたら良いのでしょうか。 ご教授ください、どうぞよろしくお願いします。 class Main{ private B b; private C c; private A[] as = new A[2]; void mainMethod(){ as[0] = b = new B(); as[1] = c = new C(); for(int i=0; i<3; i++){ as[i].method(); } } } class A{} class B extends A{ void method(){ System.out.print("It is B"); } } class C extends A{ void method(){ System.out.print("It is C"); } }

  • 継承元クラスのプロパティを参照する手段

    お世話になります。 ActionScrip3に関する質問です。 現在、カスタムクラスを勉強しております。 外部クラスでClassA、ClassBを作成し、 ClassAにある処理の途中でClassBを実行し、ClassBの中からClassAのプロパティを参照しにいく 処理を行いたいと思い、ClassBのコンストラクタからClassAのプロパティをtraceしました。 プロパティppt2は「かきくけこ」が出力されましたが、ppt1は「null」になってしまいました。 恐らく、タイムラインからClassAに対して設定したプロパティの値は見にいけていないようですが、 タイムラインから設定したプロパティの値を継承したClassBから参照しにいく方法はありますでしょうか? 下記ソースと同じ方法でなくても結構ですので、タイムラインから設定した スーパークラスのプロパティ値をサブクラスから参照・変更できる方法を ご教授いただければと存じます。 お手数ではありますが、宜しくご教授ください。 宜しくお願いいたします。 /* タイムライン側の処理 -----------------------*/ var test:ClassA = new ClassA(); test.ppt1 = "あいうえお"; test.goNext(); /* ClassAの処理 -----------------------*/ package {  // インポート記述は省略  public class ClassA {   var ppt1:String;   var ppt2:String = "かきくけこ";   // コンストラクタ   public function ClassA() { }   public function goNext():void {    var classb:ClassB = new classB();   }  } } /* ClassBの処理 -----------------------*/ package {  // インポート記述は省略  public class ClassB extends ClassA {   // コンストラクタ   private function ClassB() {    trace(ppt1);    trace(ppt2); }  } }

    • ベストアンサー
    • Flash
  • 別クラスのmainメソッドの実行

    とあるクラス「ClassA」の業務メソッドから、 別のクラス「ClassB」の「public void main」メソッドを呼び出す ことは、可能なのでしょうか?。 補足しますと、JMS経由でメッセージを受け取り、それを トリガにして別Javaアプリを起動したいのです。 浅いご説明で恐縮ですが、アドバイス頂けましたら幸いです。

  • Objective-Cクラス変数インスタンス変数

    現在iPhoneアプリを作成するために、Objective-Cの勉強をしています。しかしそこでわからないことがあり、質問させていただきました。 それは私がインスタンス変数(メンバ変数)を宣言してつかっているつもりなのですが、クラス変数の様な動きをするのです。 具体的にコードで説明します。 @implementation Main : NSObject - (void)hello{ [[Hoge alloc]init]; [[Hoge alloc]init]; } @end @implementation Hoge : NSObject NSNumber *i; - (id)init{ [super init]; NSLog(@"%d",i.intvalue); i = [NSNumber numberWithInt:123]; return self; } @end 出力結果 null 123 今手元にソースがないので正確ではないかもしれませんが、こんな感じです。hファイルにはとくになにもかいてません。 このソースの動きはmainでHogeクラスのインスタンスを二回作成することによって、initを二回呼んでいます。 疑問点は出力結果の挙動が予想外なことです。私としてはインスタンス作成時のiは初期化されていないため、 出力結果 null null になるのを期待しています。しかし二回目のinitでは前回に作成した123というデータが引き継がれています。この挙動はiはインスタンス変数ではなく、クラス変数のようにみえます。 しかしObjective-Cではクラス変数は存在しないとどっかのサイトに書いていました。 以上が質問です。なにかお気づきになった点があればごかいとういただけると幸いです。

専門家に質問してみよう