两个不同接口类型的变量,但它们是Java中相同类的实例

时间:2017-08-06 03:27:39

标签: java oop inheritance interface polymorphism

不同difference类型的两个变量之间的interface是什么,但实际上是使用same object实例化的。

例如,A类实现接口I1 I2。

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

然后我将类A的实例转换为接口类型I1,并将另一个A转换为类型I2

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

a1a2之间有什么区别?类型a1的{​​{1}}无法调用声明为接口I1的方法

3 个答案:

答案 0 :(得分:1)

a1 a2 是不同的对象。

例如:

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

你有

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

a1指的是类实现I1,因此a1只能调用I1中定义的方法derp()。它无法调用derp(),因为derp()中定义了I2。由于同样的原因,a2只能调用herp()而不能调用derp()

注意:虽然a1a2是不同的对象,但如果class A实现I1I2中的所有方法,则它们没有区别{1}}然后a1a2可以采取相同的行动。但它们仍然是两个独特的对象

答案 1 :(得分:0)

a1a2都引用A类型的对象。区分"声明的类型"是非常重要的。变量的变量,以及它引用的对象的实际类型(如果变量不是null)。

宣布

I1 a1 = <anything>;

或只是

I1 a1;

编译器唯一知道的a1是它必须引用一些实现I1的对象。因此,如果为接口a1.method(...)(或超级接口或I1)声明了方法,则只能调用方法Object。此外,a1只能分配给另一个声明为I1的变量(或超级接口,或Object),如果您将其用作参数

x.someOtherMethod(a1);

仅当参数类型为I1或超级接口或Object时才合法。

请注意,将其初始化为new A()并没有什么不同。出于&#34;允许编译器了解变量&#34;的原因,不考虑初始表达式。 (您可以使用代码将a1分配给不同类型的对象。但即使变量为final,也会应用相同的规则。)

但是,您可以让编译器通过强制转换将其视为另一种类型。将接口变量强制转换为任何其他接口始终是合法的,因为某些类可以在某个地方实现这两个接口。因此,这是合法的:

I2 x = (I2)a1;

在运行时,编译器将检查a1是否引用除I2之外还实现I1的对象。如果是这样,演员就会成功。如果不是,则抛出异常。假设没有例外,(I2)a1现在可以以任何其他I2可以使用的方式使用。因此,如果I2定义方法methodOfI2,您可以说

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

答案 2 :(得分:0)

是的,你得到了答案。就像你说的那样,你只能在a1上调用I1中定义的方法,而只能调用I2中为a2定义的方法。

用一个具体的例子来思考:

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

现在,如果我将PetDog实例化为FeedableAnimal,我就无法调用PettableAnimal中定义的任何方法。那是因为PetDog现在只表现得像FeedableAnimal。我们无法知道PetDog是Pettable,因为我们没有将它实例化为PettableAnimal。

对术语的澄清:我们不是&#34;铸造&#34; PetDog到FeedableAnimal。我们只是说在编译时,dog就像一个FeedableAnimal。在运行时,dog仍然在PetDog中承担定义的行为。