0

私はここで新しいので、事故で標準的なエチケットに従わなかった場合は事前に謝罪します。

ArrayListsを使用して、子クラスからデータを取得する方法を知りたいです。

import java.io.*;
import java.util.*;

public class MyProgrammingLab {

    public static void main(String[] args){
        ArrayList<Test> testArray = new ArrayList<>();

        testArray.add(new Test("First"));
        testArray.add(new SubTest("Last"));

        System.out.println(testArray.get(0).getFirstName());
        System.out.println(testArray.get(1).getLastName());
    }
}

public class Test {
    private String firstName;

    public Test(){
    }

    public Test(String firstName){
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }
}

public class SubTest extends Test{
    private String lastName;

    public SubTest(){
        super();
    }

    public SubTest(String lastName){
        this.lastName = lastName;
    }


    public String getLastName(){
        return lastName;
    }
}

メインの「System.out.println(test.Array.get(1).getLastName());」の行 私にエラーを投げています、そして私は理由を理解できませんか?

メインプログラムでは、1より大きいサイズのArrayListを使用します。

前もって感謝します!

4

5 に答える 5

4

提案しようとしているソリューションの使用には十分注意することをお勧めしますが、次のようになります。

System.out.println(((SubTest) testArray.get(1)).getLastName());

ただし、これを行うのは、位置1の要素がサブテストであることが確実な場合のみにしてください。そうでない場合は、を取得しClassCastExceptionます。

よくわからない場合は、おそらく確認する必要があります。

Test whatIGot = testArray.get(1);
if(whatIGot instanceof SubTest) {
   SubTest whatIActuallyGot = (SubTest)whatIGot;
   System.out.println(whatIActuallyGot.getLastName());
}

一般に、スーパークラスタイプの変数がある場合は、サブクラスのプロパティに依存することは避けてください。そうすることはコードの臭いであり、悪いデザインが原因である可能性があります。

適切な解決策には、次の2つの質問を自問することが含まれます。

  • あなたは絶対に属しているのであって、getLastName属してSubTestいないのTestですか?getLastName()にあった場合Test、それは問題を完全に解決します。
  • 本当に要素getLastNameからアクセスする必要がありますか?testArray

に属しているがgetLastName() Testのすべてのインスタンスに名前がTest付いている)、デフォルト値が適切でない場合はTest、抽象メソッドを使用して抽象クラスを作成することを検討してgetLastNameください。new Test()これにより動作が停止することに注意してください。

于 2012-11-26T23:34:11.853 に答える
1

あなたのリストはとして宣言されていArraylist<Test>ます。Testこれは、柔軟性があることを意味します。任意のインスタンス(サブクラスのインスタンスを含む)をその中に入れることができます。

この柔軟性には制限があります。後で要素を再び取得したときに、その要素についてわかるのは、その要素がのインスタンスであるということだけです。ご存知のTestように、エントリがであったかどうかを特定のタイプチェックなしで判断することはできません。 aTestまたはSubTest。(リストがエントリの正確なタイプを返す必要がある場合、getメソッドをどのように記述するかを検討してください。メソッドの戻りタイプは、渡されるインデックスに応じて変わります!)ArrayList

この柔軟性が必要な場合(そして、のインスタンスもTest一緒に格納しているので、サンプルコードがそうすることを示唆している場合SubTest)、最も簡単なオプションは、タイプをチェックしてキャストすることです。

Test secondEntry = testArray.get(1);
if (secondEntry instanceof SubTest) {
    System.out.println(((SubTest) secondEntry).getLastName());
}

他の人が指摘しているように、これはジェネリックを使用するという点をいくらか打ち負かします。

他の選択肢は次のとおりです。

  • メソッドを親クラスに移動getLastNameしてから、子クラスでオーバーライドします(親クラスがこのメソッドを持つことが理にかなっている場合)。
  • タイプベースのディスパッチで戦略パターンを実装します。

これは次のようになります。

import java.io.*;
import java.util.*;

public class MyProgrammingLab {

    public static void main(String[] args) {
        ArrayList<Test> testArray = new ArrayList<Test>();

        testArray.add(new Test("First"));
        testArray.add(new SubTest("Last"));

        for (Test aTest : testArray) {
            emit(aTest);
        }

    }

    public static void emit(Test aTest) {
        if (aTest instanceof SubTest) {
            System.out.println(((SubTest) aTest).getLastName());
        } else {
            System.out.println(aTest.getFirstName());
        }
    }
}
于 2012-11-26T23:47:00.377 に答える
0

testArray.get(1)Testではなく、タイプを返していSubTestます。SubTestあなたがそれが(あなたがinstanceofチェックするために行うことができる)であると絶対に確信しているなら、あなたは使うことができます

System.out.println(((SubTest) testArray.get(1)).getLastName());
于 2012-11-26T23:37:14.210 に答える
0

あなたがそれをこのように宣言したので:

ArrayList<Test> testArray;

Javaは、にArrayList含まれるTestオブジェクトのみを認識します。したがって、オブジェクトにそのメソッドがある場合でも、子クラスのメソッドについては認識しません

これを追加した場合:

public String getLastName(){
    return ""; // do nothing
}

クラスには、オブジェクトにメソッドがあるTestため、期待どおりにコンパイルおよび動作します。 TestgetLastName()

他の解決策はキャストを提案していますが、ジェネリックを使用する目的が損なわれるため、ここでキャストすることは強くお勧めしません。キャストしてからsを処理するような状況にはなりたくありませんClassCastException。ジェネリックスのポイントは、あなたとまったく同じ状況をエレガントに処理することです。

于 2012-11-26T23:38:01.867 に答える
0

Java継承チュートリアルを確認すると役立つ場合があります。

ArrayListを宣言するときは、正確に であるもののリストを期待していることを明示的に言っていますTest。Genericsを使用して、Testとそれを拡張するものを含めることができますArrayList<? extends Test>

これで正確な問題は解決するかもしれませんが、具象クラスを拡張するのは不十分な設計であり、デメテルTest test1 = testArray.get(0)の法則に違反しないように中間インスタンス変数(例)を使用する必要があることを知っておく必要があります。

于 2012-11-26T23:41:53.917 に答える