プロが教える店舗&オフィスのセキュリティ対策術

スーパークラスからサブクラスのメソッドを使おうとする、以下のプログラムでつまずいています。
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");
}
}

A 回答 (5件)

すいませんAクラスのところにmethodを書いてしまっていました。

これを消してやってみてください。
    • good
    • 0

>スーパークラスAにmethod()がないためコンパイルできません、Aにmethod()を作るとA.method()が実行されます。



まずここですが、これはありえません。
Javaではコンパイル時には変数の型で判断するのでAにmethod()メソッドがなければコンパイルエラーになりますが、実行時、つまりJVMは実際のオブジェクトを判断して実行します。

このため、もしAにmethodが定義されていたらコンパイルエラーにはならず、かつ実行時にはそれぞれのオブジェクトのmethod()メソッドを呼び出します。

また今回のようにAにmethod()を書きたくないのであれば普通は instanceof というものを使います。これは変数が参照している実際のオブジェクトがどのクラスのオブジェクトなのかを調べるのに使います。

以下にサンプルを示します。この方法ならAにmethodがなくても上手くいきます。

public class Main{
private B b;
private C c;
private A[] as = new A[2];
public Main(){
as[0] = b = new B();
as[1] = c = new C();

for(int i=0; i<as.length; i++){
if(as[i] instanceof B) {
((B)(as[i])).method();
}

}
}

public static void main(String[] args){
new Main();
}
}

class A{public void method(){System.out.println("A");}}

class B extends A{
public void method(){
System.out.print("It is B");
}
}
class C extends A{
public void method(){
System.out.print("It is C");
}
}
    • good
    • 0

追加、修正はコメントした3箇所。


mainMethod内のfor文のバグの存在も含め、本当にAクラスにmethodメソッドを作って実行してみたのか疑問がある。
質問のプログラムではインスタンスメソッドであったが、methodメソッドをクラスメソッドにしていたなら静的に定まっているasの型にしたがってAクラスのmethodメソッドが呼ばれる。
もし具体的なメソッドをAクラスで実装する必要がなかったりすべきでないのならmethodメソッドを抽象メソッドに(もちろんAクラスは抽象クラスに)するか、methodメソッドがpublicになってもいいのならAクラスをインタフェイスとして定義することも考えてもいいかもしれない。

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 < as.length; i++) { // as[2]は存在しない
as[i].method();
}
}

public static void main(String[] args) { // java Mainで実行できるように付加
new Main().mainMethod();
}
}

class A {
void method() { // 質問者が作成してみたところ呼ばれたというメソッド
System.out.print("It is 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");
}
}
    • good
    • 0

classの前のabstractを書き忘れ。



abstract class A{
abstract void method();
}
    • good
    • 0

class A{


abstract void method();
}
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!