Shape
基本クラスとさまざまな派生型があるとしますCircle
。
これを書くことによって、新しいオブジェクトを作成するときにすぐそこにアップキャストする理由はありますか?
Shape s = new Circle();
これの代わりに:
Circle s = new Circle();
そしてs
、これらの2つのステートメントのそれぞれによって作成されたオブジェクトは、互いに何らかの形で異なりますか?
Shape s = new Circle();
最初の例(つまり)には、Shapeが抽象または具象の基本クラスである場合でも、「インターフェイスへのコーディング」と同じ利点があると主張できます。したがって、たとえば、Circleに固有のメソッドではなく、Shapeで定義されたメソッドのみを使用する場合は、たとえば1行のコードを変更するだけで、使用している実装をSquareに簡単に変更できますShape s = new Square();
。
オブジェクトは両方の例で同じです。最初のオプションがより適切であると見なすことができる理由は、よりスタイル的なものです。インターフェイスにコーディングすると、コードベースをより簡単に拡張および変更できるようになります。
これらの2つのステートメントは、JVMに関する限り、同じオブジェクトを生成します。基本クラスまたはインターフェースにのみオブジェクトを使用することを計画していることを示すのは珍しいことではありません。たとえば、これは一般的です。
List<String> list = new ArrayList<String>();
一般的には良い考えではありませんが、それが1つであることが確実にわかっている場合は、にShape
戻すことができます。たとえば、次のように戻すことができます。Circle
Shape s
Circle c
if (s instanceof Circle) {
Circle c = (Circle) s;
// handle Circle case
}
インスタンス化されたオブジェクトはまったく同じです。
アップキャストの結果は次のとおりです。
あなたの質問に答えると、2つのオブジェクトはまったく同じです。両方の参照が同じオブジェクトを指す可能性があります。
Circle c = new Circle();
Shape s = c;
インターフェイスにコーディングすると、コードへの影響を最小限に抑えて実装クラスを変更できます。あなたがこれを持っているとしましょう:
Set<String> names = new HashSet<String>(); // using Set reference not HashSet
names.add("Frank");
names.add("John");
names.add("Larry");
for(String name: names) {
System.out.println(name + " is in the team");
}
これで要件が変わり、名前をアルファベット順に印刷する必要があります。つまり、TreeSetの代わりにHashSetを使用します。インターフェイスにコーディングし、HashSetクラスに固有のメソッドを使用していないため、変更する必要があるのは1行だけです。
Set<String> names = new TreeSet<String>(); // the only line of code that changes
names.add("Frank");
names.add("John");
names.add("Larry");
for(String name: names) {
System.out.println(name + " is in the team");
}
インターフェイスでは、依存性注入を使用することもできます。これにより、コードを記述した時点では存在しない可能性のあるクラスを使用できます。
いいえ、オブジェクト自体に違いはありません。コンパイラーが見ていると考えるものだけが異なります(たとえば、どのメソッドが使用可能か)。
このようなキャストを行う理由の1つは、オブジェクトをどのように処理するかを表現することです(代わりに、別の派生クラスを簡単に挿入できるようにするため)。
@WhiteFang34の言うことに同意します。
このインターフェースへのコーディングを参照してください。 これはあなたを助けるかもしれません。
Circle s = new Circle();
ここで、オブジェクトはクラスCricleを参照しています
形状s=new Circle(); ここでは、インターフェースを参照するオブジェクト
どちらも同じです。