• ベストアンサー

参照代入

class ApBase extends Object implements Runnable (省略) ApBase aBase = new ApBase(); Object obj = aBase; Runnable rn = obj; × コンパイラにとってobjはObjectなのでRunnnableインターフェイス参照への代入は認められません。 -----ー---- 以前質問させてもらった内容の一部なのですが・・・ 参照代入でコンパイルエラーを引き起こす場合 「is a」の関係が成り立っていない場合ですよね? なぜコンパイルエラーなのですか? Objectクラスはすべてのクラスのスーパークラスですよね・・・ Runnableとobjectはis aではないのでしょうか??????

  • Java
  • 回答数4
  • ありがとう数2

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

  • ベストアンサー
  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.3

>Runnableとobjectはis aではないのでしょうか? この場合、is aの関係が逆です。 Runnable r; Object o; として、 o = r; はできますが、 r = o; はできません。 #1さんの言う通り、 a Runnable is an Object. …正 an Object is a Runnable. …誤 です。 ポチ とは 犬 である。…正 犬 とは ポチ である。…誤 のような関係です。 もっとも、オブジェクトの階層と、 インタフェースの階層は違うものなので、 上の記述は正確ではありません。 (ただしそれを言い出すと話がややこしくなるので略します。 大筋では上記のように考えてください) キャストをすればコンパイルは通りますが、 obj変数で参照されているオブジェクトが 実際にRunnableでなかった場合、エラーが出ます。 (has aは関係ありません) >RunnableとObjectがまったく無関係 >であればキャストでもとおらないですよね・・・??? キャストは、関係ない型のときでも、コンパイルを通してしまいます。 (↑これも細かく言うと正確ではないけど) むりやり型を変えてしまうので、危険な操作なのです。 実際に互換性のある型かどうかは、プログラマが責任を持っています。

azicyan
質問者

補足

Object   +--Runnable ということになるのでしょうか・・・? 今本でも見直したのですが、上に行くと暗黙キャストで参照を渡せる、と書いてあります。 で、obj=rnは可で、rn=objは不可 というわけですね。 >ポチ とは 犬 である。…正 犬 とは ポチ である。…誤 かなりわかりやすいです!! つまり 犬=ポチという代入、ができても、ポチ=犬という代入はできない!、ということですね! サブクラスにスーパークラスの参照を代入できない という理解でよろしいでしょうか?

その他の回答 (3)

  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.4

>犬=ポチという代入、ができても、ポチ=犬という代入はできない!、ということですね! >サブクラスにスーパークラスの参照を代入できない >という理解でよろしいでしょうか? その通りです。 >Object >  +--Runnable >ということになるのでしょうか・・・? うーん、ここが「話がややこしくなる」ところです。 大掴みにはその理解でいいのですが、正確さに問題があります。 Runnableはインタフェースなので、Objectのサブクラスというわけではありません。 だから正しくは Object   +--Runnableをimplemetsした任意のクラス となります。 これを短く説明するのは難しいので、参考書の 「インタフェース」のところを読んでください。

azicyan
質問者

お礼

ありがとうございました とてもたすかりました

  • mi-si
  • ベストアンサー率35% (200/567)
回答No.2

Runnableはインターフェースでありクラスでは有りませんのでObjectのサブクラスには成りません。 Java言語仕様では1つのクラスしか継承できないので、このような仕掛けを使っています。インターフェースは関数や変数の定義だけが行われており、実装は各サブクラスに依存しています。

azicyan
質問者

補足

すいませんもう少しお願いします。 この場合 Runnnable rn =(Runnnable)obj; のようにキャストすることによってコンパイルできますよね。 キャストして通過するということは、 has a なのでしょうか・・・??? RunnableとObjectがまったく無関係 であればキャストでもとおらないですよね・・・??? 類似問題がいろいろあり混乱中です(*_*)

  • HOGERA3
  • ベストアンサー率35% (50/139)
回答No.1

まずインターフェースのことを 勉強したほうがいいとおもいます。 >Runnableとobjectはis aではないのでしょうか?????? Runnable rn = obj; でエラー。 Object is a Runnable ではありませんから。

azicyan
質問者

お礼

回答ありがとうございました

関連するQ&A

  • オブジェクト・・・参照代入・・・???

    問題(1) class ApBase extends Object implements Runnable (省略) ApBase aBase = new ApBase(); Runnable aR = aBase; ○ オブジェクトにインターフェースが実装されていることがわかる限りオブジェクト参照をインターフェイス参照に 代入することは可能です。 問題2 class ApBase extends Object implements Runnable (省略) Object obj = aBase; Runnable rn = obj; × コンパイラにとってobjはObjectなのでRunnnableインターフェイス参照への代入は認められません。 同じほんの問題です。 矛盾していませんか??? ・・・・多分僕の理解が足りないだけです(^_^;) もう少しわかりやすく教えてください・・・ お願いいたします

    • ベストアンサー
    • Java
  • Generics extends ObjectとObjectの違い

    初めて質問させていただきます。 Generics(extendsの?)の考え方についてです。 例えば、下記のような関数を作成したとします。 ======================================= public static String getHoge(Map<String , ? extends Object> checkMap){   Set<Map.Entry<String, Object>> checkMapKeySet = checkMap.entrySet();   ~ 処理 ~ } ======================================= 2行目で「型の不一致: Set<Map.Entry<String,capture#3-of ? extends Object>> から Set<Map.Entry<String,Object>> には変換できません。」とコンパイラから怒られます。 では、Objectの派生クラスをObjectとして扱えないのかと単純に理解しようとすると、以下のコードは普通にコンパイルできてしまいます。 ======================================= public static String getHoge(Map<String , ? extends Object> checkMap){   for(Map.Entry<String, ? extends Object> checkMapEntry : checkMap.entrySet()){     Object obj = checkMap.get("aa");     ~ 処理 ~   } } ======================================= 最初のコードがエラーになるなら、2つ目のコードの3行目(Object obj =の行)が何故エラーにならないのか、その違いをどのように解釈していいのか悩んでいます。 ご存じの方がいらっしゃいましたら、アドバイスでもいただけると幸いです。

    • ベストアンサー
    • Java
  • コンパイルエラー(Threadオブジェクト化)

    Runnableを継承したNormalClassをThreadとしてオブジェクト化しようとしているのですが、コンパイルエラーが出現して困っています。どうすればいいでしょうか? 下記エラー参照 Main.java:1: NormalClass は abstract でなく、java.lang.Runnable 内の abstract メソッド run() をオーバーライドしません。 下記ソース class NormalClass implements Runnable{ } class Main extends Thread{ public static void main(String args[]){ test = new Thread(new NormalClass()); } }

    • ベストアンサー
    • Java
  • Javaの多態性について質問です

    Java初心者です。どなたかお力をお貸しください。 ------------------- class Animal { public void eat() { // 汎用的なコード } } class Dog extends Animal { public void eat() { // 特化したコード } public void bite() { // Dog特有のコード } } ------------------- 上記のクラスについて質問があります。 Animal obj = new Dog(); obj.bite(); このコードがコンパイルエラーになるのは何故でしょうか? コンパイラが参照型のみをチェックし、Animalクラスにbiteメソッドが 無いため、エラーを出すと参考書に書いてありました。 つまり、スーパークラス型の参照変数にサブクラスのインスタンスを格納し、 サブクラス特有のメソッドをコールできないとはどういう意図なんでしょうか? コンパイラのチェックで引っかかるのは分かったのですが、 オブジェクト指向としては、この使い方は推奨されないということでしょうか? (Animalの参照で、Dog特有のメソッドは使わない?) 実際にJavaでプログラムを組むときには、こんな使い方をしないのですか? 有知識者の方、教えて下さい。 私は、オブジェクト指向の多態性の理解が甘いため、こんな質問をしているのだと 思います。申し訳ございません。

    • ベストアンサー
    • Java
  • PHPの参照渡しについて

    以下のようなコードがあったとき $obj = new stdClass(); $foo = $obj; この場合、動作は いわゆる【参照の値渡し】というとらえかたでよいのでしょうか? 変数$obj には、 new stdClass();という記述によって 新規に作成されたオブジェクトの参照(※正確には別のメモリ内に保持されたオブジェクトのアドレス) が保持されるわけですよね? そのとき $foo = $obj; というコードは$objが保持するオブジェクトのアドレス値を$fooという変数にも コピーするという動作を意味するわけですよね。 この場合、両変数を用いて生成されたオブジェクトのプロパティなどの状態を 共有することとができます。 しかしながら変数$fooに別の値、例えば文字列を代入すうると $foo = "文字列"; とすると$fooの値が変更され$objの値は変更されません。 対して、次のようなコードがあった場合 $foo = &$obj; というコード、これはPHPにおける参照渡しですが、 この場合は$objが指し示す、オブジェクトが保持されているメモリ上のアドレスではなく そのメモリ上に確保された変数$objそのもののアドレスが$fooという変数にコピー? されるのでしょうか? この明示的な参照渡しだと、オブジェクトの状態を共有するのはもちろん $foo = "オブジェクト破棄"; と片方に文字列を代入すると print $obj; 同様に文字列にかわってしまいます。 この本来の意味?であろう参照渡しとは実際 $fooに変数$objそのもののアドレスが保持されるという 解釈でよいのでしょうか? おくわしいかたご教授ください。

    • ベストアンサー
    • PHP
  • System::Object へのmyClassの代入

    お世話になっております。 表題の件について困っております。お分かりになる方、教えてください。 やりたいことは、Windowsフォームアプリケーションで、ボタンやListBoxなどのコントローラにあるtagプロパティに自分で作ったクラス(MY_CLASS)のオブジェクトを代入したいのですが、やり方がわかりません。 オブジェクトクラスには何でも代入できると思っていたので普通に代入しようとるすと、 'MY_CLASS' から 'System::Object ^' に変換できません。 と怒られます。 どうすれば良いのかご教授ください。 お願いいたします。

  • C++の初期化チェックに関する質問です

    C++のクラスの初期化済み、未初期化を調べる方法についてご質問させていただきます。 以下のプログラムを実行するとコメント部分//Aで実行時にエラーが発生すると思います。 class Object { int *arg ; public : Object( int len ) { arg = new int[ len ] ; } public : ~Object( ) { delete[ ] arg ; } } ; int main( ) { Object obj1 = Object( 100 ) ; Object *obj2 ; obj1 = *obj2 ; // A return 0 ; } エラー理由はobj2が初期化されていないからだと分かるのですが、 プログラマー側でobj2が初期化されているか調べる方法はあるのでしょうか? 定義時にObject *obj2 = NULL ;としてif文で回避する以外に方法が ありましたら、ぜひご教授願います。

  • 派生クラスのメンバを基底クラスの参照に代入(C++

    文末のコードのように、 基底クラスで、派生クラスのメンバの参照を持つのはまずいでしょうか。 (classではなくstructにしているのは質問上でのpublic:の省略のためだけです) 初期化順序的には、基底クラスの参照先は、 基底クラスのコンストラクタが走る時点で初期化されていないので、 コンストラクタ内で参照に対して何かしようとすると問題になると思っています。 基底クラスのコンストラクタ内で派生クラスメンバの参照に対して何かしなければ、 参照は有効で、派生クラスのコンストラクタ実行後であれば 問題なく動くと思ってよいでしょうか。 struct A { int& m_ref; A(int& ref) : m_ref(ref) { } }; struct B : public A { int m_obj; B() : A(m_obj) { } };

  • 【C++】オブジェクト配列の動的確保

    Objectがクラスとして、以下のようなプログラムを書きました Object **obj; obj = new Object*[100]; for(i=0;i<100;i++){     obj[i] = new Object(a,b,c);     obj[i]->Run();     delete obj[i]; } delete [] obj; するとdeleteの所でエラーになります。 (確保していない領域をdeleteしようとしたときのような) 何か間違っているのでしょうか。 何故かデバッガでは通ってしまいます。 環境:XP、VisualStudio2005 何卒よろしくお願いいたします。

  • オブジェクトの参照を返す関数の扱い

    オブジェクトの作成と関数との関係を勉強していますが参照の使い方に関して質問させていただきたいと思います。 以下のような簡単なプログラムを作りました。 myclass.cpp myclass.h で記述されたクラスmyclassは整数を一つ持ち、show_value関数でその整数を表示し、say_heyで"hey"という文字を出力するというものです。 このクラスを利用するプログラムとしてmain.cppをつくりました。このなかには2つの関数が使われます。 -オブジェクトをつくりそれをオブジェクトとして返す関数(return_obj)   -オブジェクトをつくりそれの参照を返す関数(return_ref_obj) これらの関数を用いてオブジェクトをつくり、そのオブジェクトを戻り値としてmainのなかでオブジェクトのshow_value関数で保持する整数を表示する、というものです。 myclass.h-------------------------------- class Myclass{ public: int my_int; Myclass(); ~Myclass(); void show_value(); void say_hey(); }; myclass.cpp---------------------------------- #include "myclass.h" #include <iostream> using namespace std; Myclass::Myclass(){}; Myclass::~Myclass(){}; void Myclass::show_value(){ printf("%d\n", my_int); } void Myclass::say_hey(){ printf("hey\n"); } main.cpp------------ #include <iostream> #include "myclass.h" using namespace std; //オブジェクトをつくりそれをオブジェクトとして返す関数(return_obj)   Myclass return_obj(int int_in){ Myclass myobject; myobject.my_int = int_in; //引数をオブジェクトのmy_intに渡す return myobject; } //オブジェクトをつくりそれの参照を返す関数(return_ref_obj) Myclass& return_ref_obj(int int_in2){ Myclass myobject; myobject.my_int = int_in2;   //引数をオブジェクトのmy_intに渡す Myclass& ref_of_myclass = myobject; return ref_of_myclass; } void main(){ Myclass returned_obj = return_obj(1); //関数に1を渡し、1を保持するオブジェクトを作成 returned_obj.show_value(); //整数(1)表示 returned_obj.say_hey(); Myclass& ref_obj = return_ref_obj(2); //関数に2を渡し、2を保持するオブジェクトを作成し参照として受け取る ref_obj.show_value(); //整数(2)表示 ref_obj.say_hey(); } プログラムを実行した出力------------------- 1 hey -858993460 hey このようにオブジェクト自体を返してコピーしたもの(return_obj使用)はshow_valueでただしくオブジェクトに保持された数が表示されますが 参照でオブジェクトを返したもの(return_ref_obj使用)はアドレスのような数列が表示されます。 質問A これはオブジェクトの参照を返す関数(return_ref_obj)でオブジェクトを作成しても、そのオブジェクトが関数の中でのみ実在しており、関数がおわるとその実体がなくなるためではないかと解釈しているのですがそれで正しいでしょうか? 質問B 関数でオブジェクトを作成してそれをプログラム本体に渡すときはreturn_objのようにオブジェクト自体をコピーしなければ参照などで渡すことはできないのでしょうか? クラスと参照自体勉強を始めたばかりで色々と初歩的な間違いもあるとは思いますが、よろしくお願いします