Javaの抽象クラスとオブジェクトを格納する配列の仕組みについての理解について

このQ&Aのポイント
  • Javaの抽象クラスとオブジェクトを格納する配列の仕組みについて質問があります。
  • 質問の内容は、配列に格納されたオブジェクトが抽象クラスのインスタンスでありながら、抽象メソッドを呼び出すことができる理由や、抽象メソッドがそれぞれのサブクラスのメソッドとして呼び出される仕組みについてです。
  • また、オブジェクトとインスタンスの違いや配列の仕組みについても理解したいと思っています。
回答を見る
  • ベストアンサー

抽象クラスとオブジェクトを格納する配列(java)

独習java第4版でわからない所があります。 abstract class Widget { String color; abstract int getMass(); public String toString() { return getClass().getName() + ": " + color + ", " + getMass(); } } class WidgetA extends Widget { final static int MASS = 4; WidgetA(String color) { this.color = color; } int getMass() { return MASS; } } class WidgetB extends Widget { final static int MASS = 1; WidgetB(String color) { this.color = color; } int getMass() { return MASS; } } class WidgetC extends Widget { final static int MASS = 5; WidgetC(String color) { this.color = color; } int getMass() { return MASS; } } class WidgetD extends Widget { final static int MASS = 17; WidgetD(String color) { this.color = color; } int getMass() { return MASS; } } class WidgetTypes { static int NUMWIDGETS = 6; public static void main(String args[]) { // 部品を格納する領域を宣言して割り当てる Widget widgets[] = new Widget[NUMWIDGETS]; // 部品を作成する widgets[0] = new WidgetC("Red"); widgets[1] = new WidgetA("Green"); widgets[2] = new WidgetD("Yellow"); widgets[3] = new WidgetB("Magenta"); widgets[4] = new WidgetA("Black"); widgets[5] = new WidgetC("White"); // 部品を処理する int totalMass = 0; for(int i = 0; i < NUMWIDGETS; i++) { Widget w = widgets[i]; System.out.println(w); totalMass += w.getMass(); } // 総重量を表示する System.out.println("Total mass = " + totalMass); } } これはある問題の解答ですが、僕にはどうしても理解出来ない部分があります。 mainのforループ内で Widget w = widgets[i]; totalMass += w.getMass(); となっています。 この仕組がわかりません。 まず Widget w = widgets[i] でWidget型の変数wにWidget型のwidget[i]を代入しているのにw.getMass()がエラーにならない理由がわかりません。(Widgetクラスは抽象クラスなのにwがWidgetクラスのインスタンスになっている?) これは 抽象メソッド( abstract int getMass() ) があるためでしょうか? ちなみにWidgetクラスとそのサブクラスからこの抽象メソッドを削除したらコンパイルエラーが出ました。 ではなぜ抽象クラスの抽象メソッドから、そのサブクラスのメソッドまで範囲が伸びるのでしょうか? どういう仕組でしょうか? この質問を書きながら思ったのですが、どうも配列の仕組みや抽象クラス・メソッドの仕組み、「オブジェクト」と「インスタンス」の違いがよくわかってないようです。 多分問題の本質はそこにあると思うんです。 駄文で申し訳ないです。 よろしくお願いします。

  • Java
  • 回答数3
  • ありがとう数0

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

  • ベストアンサー
  • kztk
  • ベストアンサー率53% (59/110)
回答No.3

質問者さんがわかっていないのは「ポリモーフィズム」ですね。それはさておき、 > Widget w = widgets[i] でWidget型の変数wにWidget型のwidget[i]を代入しているのに widgets[i]に入っているのはWidgetクラスのインスタンスではなく、 WidgetCやWidgetAやWidgetDクラスのインスタンスです。 具体的には widgets[0] = new WidgetC("Red"); としているのですから、forループの最初(i=0)の Widget w = widgets[i]; System.out.println(w); totalMass += w.getMass(); でwに代入されるのは、WidgetCクラスのインスタンスです。 w.getMass()で呼ばれるのもWidgetCクラスのgetMass()です。

その他の回答 (2)

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.2

WidgetA、WidgetB、WidgetC、WidgetD ちょっとだけ違う似たようなクラスですね。 配列にしないで、一個ずつ処理すると、 ステップが冗長になると思いませんか? 「なんとなく似ているクラス」でまとめる ことができれば便利ですよね。 そこで登場するのがインターフェースとか 抽象クラスとか言うものです。 widgets[]の形式はWidgetですが、個別の 要素の実体はWidgetAとかWidgetBです。 どれもgetMassメソッドを持っていますから w.getMass()はエラーになりません。 というか、抽象クラスの抽象メソッドでの 定義があるからgetMassがないとエラーに なります。つまり、Widget型、あるいはその サブクラスには必ずgetMassがあるはず (なければならない)ということです。 抽象メソッドを削除すると、getMassは 各クラスの勝手なメソッドになるわけで、 個別のWidgetAやWidgetBにあるかないか 分かりませんよね。少なくともWidget型には 無いのですから、そういうメソッドは使えない ことになります。

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.1

> この質問を書きながら思ったのですが、どうも配列の仕組みや抽象クラス・メソッドの仕組み、「オブジェクト」と「インスタンス」の違いがよくわかってないようです。 > 多分問題の本質はそこにあると思うんです。 違う、分かっていないのはそこじゃない。 抽象クラスも普通のクラスも(これから出るであろうインターフェースも)、それを派生させたクラスでメソッドをオーバーロードしたときの動作は変わりません。 継承したクラスでオーバーロードしたメソッドを継承元のメソッドの代わりに実行するだけです。 抽象クラスの抽象メソッドはその取って代わられたメソッドが、外の形だけあって実体が無いという状態になっているだけです。 だから、継承とオーバーロードの部分をもう一度勉強しましょう。

関連するQ&A

  • 抽象クラスからオーバーライドについて

    EclipseでJavaを勉強始めました。 抽象クラスからオーバーライドするところで質問致します。 抽象クラスとして、「面積を計算する」というメソッドをもつDiagramクラスを定義しました。それを継承して、「四角形の面積を計算する」というメソッドをもつSquareクラスと、「三角形の面積を計算する」というメソッドをもつTriangleクラスを定義しました。 Squareクラス、Triangleクラスからインスタンスを生成して、四角形、三角形の面積をコンソールに表示させるという簡単なプログラムです。 このとき、main関数と3つのクラスの関係についてお尋ねします。 (1)iagram.java、Square.java、Triangle.javaそれぞれにクラス定義とmain関数を持たせるパターン public abstract class Diagram { // 面積計算定義(抽象メソッド) public static void main(String[] args) { } } public class Square extends Diagram{ //四角形の面積の計算定義 public static void main(String[] args) { //四角形の面積の計算と表示 } public class Triangle extends Diagram{ //三角形の面積の計算定義 public static void main(String[] args) { //三角形の面積の計算と表示 } (2)sample.javaというファイルにまとめ、その中にこの3つのクラス定義とmain関数を一つ持たせるパターン public class sample { public static void main(String[] args) { //四角形の面積の計算と表示 //三角形の面積の計算と表示 } } abstract class Diagram { // 面積計算(抽象メソッド)定義 } class Square extends Diagram{ //四角形の面積の計算定義 } class Trapezoid extends Diagram{ //三角形の面積の計算定義 } この二通りを考えて、どちらも実行できたのですが、どちらの方がJavaらしいプログラムと思われますでしょうか?

    • ベストアンサー
    • Java
  • javaの配列とクラス

    abstract class abstract_class{ } class subclassA extends abstract_class{ int num = 1; } class subclassB extends abstract_class{ int num = 2; } class subclassC extends abstract_class{ int num = 3; } class Main{ public static void main(String args[]){ int sum = 0; abstract_class var[] = new abstract_class[3]; var[0] = new subclassA(); var[1] = new subclassB(); var[2] = new subclassC(); for(int i=0;i<3;i++) sum += var[i].num; System.out.println(sum); } } これをコンパイルすると Main.java:23: シンボルを見つけられません。 シンボル: 変数 num 場所 : abstract_class の クラス for(int i=0;i<3;i++) sum += var[i].num; ^ エラー 1 個 というエラーが出るのはなぜでしょうか? var[i]はみなsubclassA,subclassB,subclassCが代入されているのに、numはabstract_classの変数となっています。 よくわかりません。 よろしくお願いします。

    • ベストアンサー
    • Java
  • クラスメソッドのみのクラスのオブジェクト生成は不可??

    あるテキストのjavaの問題です。 public class Draw{   static void pixel(int x,int y){     /*座標(x、y)に点を描画*/   }   static void line(int x1,int y1,int x2,int y2){     /*座標(x1、y1)~(x2、y2)に線を引く*/   } } で、これを実行するための以下のようなクラス public class TestDraw{ <ここに入力> } という問題なのですが2つまでは絞れたのですが、 (1) public static void main(String args[]){   Draw d = new Draw().line(10,10,20,30); } ↑× (2) public static void main(String args[]){   Draw.line(10,10,20,30); } ↑○ (2)はlineメソッドがstaticメソッドだからオブジェクト生成しなくても良い、ということなんですが (1)も正解のような気がするのですが・・・ 解説によると「lineはvoidなのでnew Draw().line(10,10,20,30);とすれば正解、とあります。 どうもいまいち理解できません。 クラスメソッドはオブジェクト生成しなくとも良い→オブジェクト生成できない ということなのでしょうか? それからちなみに、public classって2つ記述できないんではありませんでしたか?

    • ベストアンサー
    • Java
  • 抽象クラス について

    obj.write();した時 class super1 の write()が呼ばれ その後 class HINA の write()が呼ばるのか? 直接 class HINA の write()が呼ばるのか? どう呼び出してるのか 教えてください abstract class super1 { abstract void write(); } class HINA extends super1{ void write() { System.out.println( "LOVE HINA" ); } } class test { public static void main( String args[] ) { super1 obj = new HINA(); obj.write(); } } }

  • プログラムの合体。

    jump7799_4836さん 2018/7/2103:34:44 public class Test2 { public static int メソッド () { System.out.println("メソッド()が呼ばれました"); return 0; } public static int メソッド (int i) { System.out.println("メソッド(int i)が呼ばれました"); return i; } public static int メソッド (int i, int j) { System.out.println("メソッド(int i, int j)が呼ばれました"); return i; } public static int メソッド (short s) { System.out.println("メソッド(short s)が呼ばれました"); return s; } public static int メソッド (double d) { System.out.println("メソッド(double d)が呼ばれました"); return (int) d; } } public メソッド class Test2 { public メソッド static void main(String[] args) { Test2.メソッド (); Test2.メソッド (1); Test2.メソッド (1,2); Test2.メソッド (1.1); Test2.メソッド ((short) 1); Test2.メソッド ((double)1); } } kouzou@GD348ZZD9:/WORK$ javac Test2.java Test2.java:29: エラー: class、interfaceまたはenumがありません public メソッド class Test2 { ^ Test2.java:30: エラー: <identifier>がありません public メソッド static void main(String[] args) { ^ エラー2個 2つのプログラムが合体することってあるのですか? いつもすみません。 解説のほど、宜しくお願い申し上げます。

    • ベストアンサー
    • Java
  • インターフェイス 抽象クラス

    PHP初心者です。 xampp1.7.0(最新)でアパッチなど一括ダウンロード クラスの概念は分かりましたが、インターフェイス、及び抽象クラスについて理解が追い付きません。 下記コードをご覧ください。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <? abstract class AbstractClass { abstract public function test1(); } class Impl1 extends AbstractClass { public function test1() { print "こんにちは\n"; } } class Impl2 extends AbstractClass { public function test1() { print "ありがとう.\n"; } public function hoge() { print "さようなら\n"; } } $i1 = new Impl1(); $i1->test1(); $i2 = new Impl2(); $i2->test1(); ?> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 抽象クラスが上にありますが、中身がないので継承し、そのクラスの中で処理させています。抽象クラスの必然性が理解できません。まあこのコード事態がものすごく短いので、その必然性がないと思うのですが、例えばもっと長いコードになったときなどは抽象クラスは絶対使った方がいいということになるのでしょうか。 さらに全て抽象クラスであればインターフェイスを利用できるようですが、インターフェイスのメリットにつき理解が追い付きません。 どなたかご教授お願いいたします。

    • ベストアンサー
    • PHP
  • Java初心者です

    次のようなプログラムを作りました interface Vehicle{ void drive(); } abstract class Animal{ abstract void show(); } class Lion extends Animal{ public void show(){ System.out.println("ライオンです"); } } class Horse extends Animal implements Vehicle{ public void show(){ System.out.println("馬です"); } public void drive(){ System.out.println("乗り物として使えます"); } } class Elephant extends Animal implements Vehicle{ public void show(){ System.out.println("象です"); } public void drive(){ System.out.println("乗り物として使えます"); } } class Bear extends Animal{ public void show(){ System.out.println("熊です"); } } class twentyeight{ public static void main(String args[]){ Animal an[]; an = new Animal[4]; an[0] = new Lion(); an[1] = new Horse(); an[2] = new Elephant(); an[3] = new Bear(); for(int i = 0;i < an.length;i++){ if(an[i] instanceof Vehicle){ an[i].drive();//ここにエラーが出る } else{ an[i].show(); } } } } インターフェイスを実装しているオブジェクトを判別し、そのdriveメソッドの呼び出しをしたいのですができません、どなたか教えてください。

    • ベストアンサー
    • Java
  • メソッドのオーバーライド(java)

    class A3{ void hello(){ System.out.println("A3"); } void hello(int i){ System.out.println("A3"+i); } } class B3 extends A3{ void hello(){ System.out.println("B3"); } } class C3 extends B3{ void hello(String s){ System.out.println("C3"+s); } } class MethodOverriding3{ public static void main(String args[]){ A3 obj = new C3(); obj.hello(); } } 上のプログラムを実行すると"B3"と表示されまが、どうしてクラスBのメソッドが実行されるのでしょうか? クラスAのメソッドが無視される仕組みがわかりません。 また、クラスMethodOverriding3でobj.hello("abc")としてコンパイルすると mo.java:25: シンボルを見つけられません。 シンボル: メソッド hello(java.lang.String) 場所 : A3 の クラス obj.hello("abc");   ^ エラー 1 個 とエラーが出ます。 どうしてでしょうか? 誰か教えてください、お願いします。

    • ベストアンサー
    • Java
  • java内部クラスについて

    内部クラスがstaticな場合 public class mainclass{   public static void main(String[] args) {     innerClass ic = new innerClass();   }   public static class innerClass{   } } と innerClass ic = new innerClass();で動作しnewできますが、 class が static でない場合どういう書き方になりますでしょうか? 色々と理解不足がある状況だとおもいますがよろしくお願いいたします。

  • 抽象クラス、インターフェイスについて

    少し長いですが、以下にコードを書きました。これでコンパイルすると、13個ほどエラーが出て、何がなんだかわかりません。何が間違っているのでしょうか?よろしくお願いします。ちなみに本を見ながらの独学です。 //のりものインターフェイス interface iVehicle { abstract void show(); } //車くらす class Car implements iVehicle { private int num; private double gas; public Car(int n, double g)) { num = n; gas = g; System.out.println("ナンバー" + num +"ガソリン量" + gas +"の車を作成しました"); } public void show() { System.out.println("車のナンバーは" + num +"です"); System.out.println("ガソリン量は" + gas +"です"); } } //飛行機クラス class Plane extends Vehicle { private int flight; public Plane(int f) { flight = f; System.out.println("便" + flight +"の飛行機を作成しました"); } public void show() { System.out.println("飛行機の便は" + flight +"です"); } } class sample8 { public static void main(String args[]) { iVehicle ivc[]; ivc = new iVehicle[2]; ivc[0] = new Car(1234, 20.5); ivc[1] = new Plane(232); for(int i=0; i<ivc.length; i++){ if(vc[i] instanceof Car) ivc[i].show(); } } }

    • ベストアンサー
    • Java