0
Object aThing = new Integer(25);

メソッド呼び出しaThing.intValue()はコンパイラ エラーです。この場合、ポリモーフィズムが機能しないのはなぜですか?

また、私の教科書には、少し複雑な関連ステートメントがあります。

操作を実行できるかどうかは、参照されるオブジェクトのタイプではなく、参照のタイプによって決まります。

それについて簡単に説明していただけますか?

Computer[] labComputers = new Computer[10];ポリモーフィズムで動作する場所

public class Computer {
    int ram;
    public Computer(int rm){
        ram= rm;
    }
    public String toString(){
        String result = "ram is " + ram;
        return result;
    }
}


public class Notebook extends Computer{
int size;
public Notebook(int rm, int sz){
    super(rm);
    size = sz;
}
@Override
    public String toString(){
        String result = super.toString() + " size is " + size;
        return result;
    }

}

追加:中間のどこかにあると思います

labComputer[1] = new Notebook(2,15);
labComputer[2] = new Computer(2);

メソッド calllabComputers[1].toString()の場合、ポリモフィズムにより正しいメソッドtoStringが呼び出されることが保証されます。私の考えlabComputer[1] = new Notebook(2,15);では に相当しObject o = new Integer(25);ます。しかし、ポリモーフィズムは、Object-Integer の例ではなく、Computer の例で機能しました。なんで?

4

4 に答える 4

5

であるにもかかわらずIntegerObjectObjectはないため、 のメソッドはなく、 のメソッドしかIntegerありません。IntegerObject


操作を実行できるかどうかは、参照されるオブジェクトのタイプではなく、参照のタイプによって決まります。

つまり、参照されるオブジェクトにはより多くの機能が含まれていても、参照のタイプがオブジェクトのタイプと異なる場合、参照のタイプの機能のみ利用可能になります。

以下では:

Object aThing = new Integer(25);

の型はaThingとして宣言されていObjectます。実装にはそれ以上のものが含まれていますが、変数のIntegerが ではなく であるため、実装に含まれているものはすべて表示されなくなりましたObject。との両方ObjectInteger共通のメソッドがありますが、今後は によって提供されるものにしかアクセスできませObjectん。IntegerObject


2 番目の例では、 と の両方に共通のメソッドがありますが、いずれかのメソッドを呼び出すと、実際の型のメソッドが呼び出されることを意味しObjectますInteger。したがって、この場合、toString()onを呼び出すと、 ではなくのメソッドaThingが呼び出されます。したがって、これはアクセスの問題にすぎません。として宣言するという事実は、のメソッドが呼び出しに応答することを意味するのではなく、 に存在するメソッドと存在しないメソッドが利用できないことを意味するだけです。IntegertoString()ObjectObjectObjectIntegerObject


例:

class Computer {
    public int getInstalledOperatingSystems() { return 3; }
}

class Desktop extends Computer {
    public String getShapeOfCase() { ... }
}

class Notebook extends Computer {
    public int getInstalledOperatingSystems() { return 1; }
    public String getBrand() { ... }
    public void closeLid() { ... }
}

を作成しましょうNotebook:

Notebook n = new Notebook();

次のメソッドがあるとします。

public String showStatistics(Computer computer) {
    result = "Operating systems: " + computer.getInstalledOperatingSystems();
    return result;
}

Notebook上記で定義した でこのメソッドを呼び出すと、次のようになります。

showStatistics(n);

aはであるNotebookため、メソッドは を受け取ります。のメソッドを呼び出すことができます。それを呼び出すと、の実装をオーバーライドするため、結果として受け取ります。ただし、 が渡されていることを認識していないため、提供する他のメソッドを呼び出すことはできません。とにかく、 があり、 が持っていない他のメソッドを知りません。NotebookComputerNotebookgetInstalledOperatingSystems()Computer1NotebookComputershowStatistics()NotebookNotebookComputerComputer

代わりにを送信することもできますし、Desktop明日にはを拡張する やGamingComputerを拡張DesktopするServerクラスを作成することもできますComputer。それも送れます。しかし、は を参照していることを認識していないため、 の特定の特殊なメソッドにshowStatistics()はアクセスできません。が書かれたとき、それは発明されていませんでした。ServershowStatistics()ServershowStatistics()

Serverこれは、 aが常に aであっても、 a が必ずしも a ではないというステートメントと一致してComputerComputerますServer


でも確認できます。したがって、コンピューターだけでなくで渡される可能性があることがわかっNotebookている場合は、それを探すことができ、Notebookのメソッドを呼び出すこともできますが、 を見ていることを確認する必要がありますNotebook

if (computer instanceof Notebook) {
    // this is definitely a Notebook, so you can assure the compiler
    // of that explicitly, by using a cast
    Notebook notebook = (Notebook) computer;

    result += "This isn't just a generic computer, it's actually a notebook! ";

    // now that you have a variable of type Notebook, you can call
    // whatever Notebook provides
    result += "It's produced by: " + notebook.getBrand();
}
于 2012-10-14T23:14:08.007 に答える
5

変数がObjectクラスのものであるため機能しないため、クラス内のメソッドのみを使用できます Object。として使用する場合はInteger、最初に (ダウン) 型キャストを行う必要があります。

Integer aInteger = (Integer)aThing;
//it could maybe work
aInteger.intValue();

さて、なぜうまくいくのでしょうか?型キャストが機能しない場合、ダウンキャストは ClassCastException をスローする可能性があるためです。

あなたの例に基づいて、ポリモフィズムがどのように機能するかを示す基本的なコードを投稿します。

class Animal {
    public void move() {
        System.out.println("I'm an animal and I can move.");
    }
}

class Cat extends Animal {
    //this means a Cat would change the move behavior from the Animal instance
    @Override
    public void move() {
        System.out.println("I'm a cat and I can move.");
    }
}

class Dog extends Animal {
    //this means a Cat would change the move behavior from the Animal instance
    @Override
    public void move() {
        System.out.println("I'm a dog and I like to run.");
    }
    public void bark() {
        System.out.println("I can bark!");
    }
}

public class AnimalTest {
    public static void main(String[] args) {
         //it will take the behavior of the Animal class reference
         Animal animal = new Animal();
         //it will take the behavior of the Cat class reference
         Animal cat = new Cat();
         //it will take the behavior of the Dog class reference
         Animal dog = new Dog();
         //this will invoke the Animal#move method
         animal.move();
         //this will invoke the Cat#move method because it was overriden in the Cat class
         cat.move();
         //this will invoke the Dog#move method because it was overriden in the Dog class
         dog.move();
         //this line won't compile if uncommented because not all animals can bark.
         //dog.bark();
         //if you want to make the dog barks, then you should use the downcasting
         ((Dog)dog).bark();
         //note that this will only work for Dog class reference, not for any other class
         //uncomment this line and the code will compile but throw a ClassCastException
         //((Dog)cat).bark();
    }
}
于 2012-10-14T23:15:06.680 に答える
2

このように考えてください。犬はオブジェクトであり、犬のクラスには次のようなメソッドがあります。

dog.bark()

Dog を階層の上位のオブジェクトにキャストすると、特定性が低くなります。

Object o = dog;

o がオブジェクトであることがわかっているだけで、オブジェクトの種類がわからないため、このオブジェクトが吠えることができるかどうかはわかりません。

階層を上に移動すると、ほとんどの場合、所有しているものについて具体的でなくなるため、機能が失われます。

于 2012-10-14T23:17:04.293 に答える
0

コンパイラは、オブジェクトがどのような型であると予想されるかを伝える必要があるため、クラスを検索してメソッドが正当かどうかを確認できます。

だからあなたは言うことができますObject aThing = new Integer(25);が、あなたは言いたいですint thingValue = (Integer)aThing.intValue();

MyClass のサブクラスである MySubClass オブジェクトがあり、MyClass で定義されたメソッドを呼び出したい場合 (たとえ MySubClass で再実装されていても)、次のように言えます。

Object myObject = new MySubClass();
int someValue = (MyClass)myObject.methodInMyObject();
于 2012-10-14T23:30:22.997 に答える