2017-08-06 3 views
-1

異なるinterfaceタイプの2つの変数の間のdifferenceは実際にはsame objectでインスタンス化されます。異なるインタフェースタイプの2つの変数ですが、Javaの同じクラスのインスタンスです

たとえば、クラスAはインターフェイスI1 I2の両方を実装します。

interface I1 {} 
interface I2 {} 
class A implements I1, I2 { 
... 
} 

は、それから私は、インターフェイスタイプI1にクラスAのインスタンスをキャストし、a1a2の違いは何ですか?I2

I1 a1 = new A(); 
I2 a2 = new A(); 

を入力するために、別のAをキャストタイプI1a1は、メソッドを呼び出すことはできませんインターフェースI2?

+0

a1とa1の間に違いはありません。 a1とa2の間には、どのメソッドを呼び出すことができるかという違いがあります。 – MaxZoom

+2

常にキャストすることは、ビューをオブジェクトに縮小する**ことに注意してください。実際に**オブジェクトのタイプを変更する**ではありません。たとえば、 'System.out.println(a1.getClass())'のようなことをした場合、 'I1'にキャストしたとしても' class A'のようなものが読み込まれます。しかし、 'I1'だけを必要とすれば、将来的に' I1'の別の実装といつも簡単にオブジェクトを交換することができるので、ビューを減らすことはモジュール性には良いことです。またコンパイラは 'I1'にキャストした後に' I2'のメソッドを呼び出すのを防ぎます。コンパイル時に 'I1'も' I2'です。 – Zabuza

+0

コンパクトでは: 'a1'と' a2'は、キャスティングの後でさえ、 'A'、' I1'、 'I2'のままです。しかし、キャスト後*の実数型*は隠され、コンパイラーはキャストバックせずに安全でない*メソッド呼び出しを行うのを防ぎます。 – Zabuza

答えて

0

両方a1a2タイプAのオブジェクトを参照すると宣言。変数の「宣言された型」と、それが参照するオブジェクトの実際の型(変数がnullでない場合)を区別することが重要です。

あなたは

I1 a1 = <anything>; 

か、単に

I1 a1; 

を宣言すると、コンパイラはおよそa1を知っている唯一のものは、それがI1を実装し、いくつかのオブジェクトを参照しなければならないということです。したがって、I1インターフェイス(またはスーパーインターフェイス、またはObject)に対してメソッドが宣言されている場合にのみ、メソッドa1.method(...)を呼び出すことができます。また、a1I1(またはスーパーインタフェース、またはObject)として宣言別の変数に割り当てることができ、そしてあなたは、パラメータ

x.someOtherMethod(a1); 

としてそれを使用する場合には、パラメータの型I1である場合にのみ法的ですスーパーインタフェース、またはObjectです。

new A()に初期化しても差はありません。 「コンパイラが変数について知ることができるもの」の目的のために、最初の式は考慮されていません。 (異なるタイプのオブジェクトにa1を割り当てるコードがあるかもしれませんが、変数がfinalであっても同じルールが適用されます)。

ただし、キャストによって別のタイプとして扱うコンパイラを得ることができます。インターフェイス変数を他のインターフェイスにキャストすることは常に正当です。なぜなら、あるクラスが両方のインターフェイスを実装できる可能性が常にあるからです。したがって、これは合法である:

I2 x = (I2)a1; 

実行時に、コンパイラはa1I1に加えてI2を実装するオブジェクトを参照するかどうかをチェックします。そうであれば、キャストは成功する。そうでない場合、例外がスローされます。例外がないと仮定すると、(I2)a1は他のどのような方法でも使用できます。I2したがって、I2は方法methodOfI2を定義している場合、あなたは

((I2)a1).methodOfI2(...parameters...) 
0

うんを言うことができ、あなたは答えを得ました。あなたが言ったように、あなたはa1のI1で定義されたメソッドと、a2のI2で定義されたメソッドだけを呼び出すことができます。

は、具体的な例を挙げてそれについて考える:私はFeedableAnimalとしてPetDogをインスタンス化した場合

public class PetDog implements FeedableAnimal, PettableAnimal { 
    ... 
} 
... 
FeedableAnimal dog = new PetDog(); 

は今、私はPettableAnimalで定義された任意のメソッドを呼び出すことはできません。これは、PetDogがFeedableAnimalのようにしか動作しないためです。 PetdogはPettableとしてインスタンス化していないため、PettogがPettableであることはわかりません。

用語の明確化:私たちはPetDogをFeedableAnimalに「キャスト」していません。コンパイル時に、犬はFeedableAnimalのように振る舞います。実行時には、犬はまだPetDogで定義された動作を引き継ぎます。

+1

'PetDog'は' FeedableAnimal'のように動作するとは言いません。 'dog'は' FeedableAnimal'のように動作すると言うと、より正確です。 'PetDog'は常に両方のインターフェースのメソッドを持ちます。 – ajb

+0

良い点が編集されました。 – nareddyt

+0

* PetDogがPettableであることを知る方法がありません* - 私たちは方法を持っています - 'instanceof'(および他の複数の方法) – Oleg

1

a1a2は異なるオブジェクトです。例えば

interface I1 { 
    public void derp(); 
} 
interface I2 { 
    public void herp(); 
} 

、あなたが

I1 a1 = new A(); 
I2 a2 = new A(); 

a1を持っているが、クラスを参照するには、I1がそうa1derp()あるI1で定義されたメソッドのみを呼び出すことができます実装します。 derp()derp()I2で定義されているため、呼び出すことはできません。 a2は同じ理由でherp()にしかコールできませんが、derp()にはコールできません。

a1a2は異なるオブジェクトですが、class Aが、その後a1I1I2のすべてのメソッドを実装し、a2が同じ行動することができれば、彼らは差がないことができますが。彼らはまだ2つの特徴的なオブジェクトです

関連する問題