关于多态性的Java接口问题

时间:2011-03-22 00:02:04

标签: java interface polymorphism

所以我有这个:

interface C {
    void shutUp();
}

class A {
    public void speak() {
       System.out.println("Class a");
    }
}

class B extends A implements C {
    public void shutUp() {
        System.out.println("Saying nothing...");
    }

    public void speak() {
        System.out.println("Class B");
    }
}

如果我这样做,它会起作用:

A obj = new B();
obj.speak()

但我做不到obj.shutUp()为什么不呢?我有一种感觉,我只是对一些非常基本的东西感到困惑。

谢谢!

11 个答案:

答案 0 :(得分:2)

A的静态类型未连接到C,因此您无法执行此命令,它将是相同的:

A obj = new A();
obj.shutUp();

(这显然是非法的..)
唯一可以同时使用两者的是B

B obj = new B();
obj.shutUp();
obj.speak();

这与Java static typing

这一事实有关

答案 1 :(得分:1)

因为A不是C - 它没有实现接口 - 并且你不能以这种方式实例化接口,因为没有默认的构造函数。

A类型的引用没有方法shutUp(),所以毫无疑问它不起作用。

您的代码使用了错误的关键字:Java的classinterface。案件很重要。

答案 2 :(得分:0)

您的obj具有来自班级A的界面,因为它是您变量的类型。

答案 3 :(得分:0)

obj的类型定义为A;因此,obj只能使用A可用的成员。由于C继承自AC要求所有成员都被视为A的形式,这就是为什么它允许您创建新CA变量中。只有将其投放到C类型,才能使用属于C的所有成员。

答案 4 :(得分:0)

在你的问题中是错误的:你不能创建C对象因为它的界面 - 所以我认为你想要创建B对象,然后:

这是因为obj是A而不是C,要使用shutUp方法,你可以:

((C) obj).shutUp() // cast to C type
((B) obj).shutUp() // cast to B type

或宣布:

B obj = new B();
obj.shutUp();

或者:

C obj = new B(); // (!) but: you can't (without casting) call speak method
obj.shutUp();

答案 5 :(得分:0)

  

obj = new C();

由于C是接口,因此无法创建接口实例。请更正问题。

答案 6 :(得分:0)

为什么你不能在obj上调用shutUp的原因是:

obj不是对象,它是指针或引用。你做新B()时创建的对象是一回事,obj(或“你如何使用对象”)是一个单独的东西。您可以在引用的帮助下使用该对象(在本例中为obj),它允许您访问实际对象的不同侧面。

如果用于访问对象的引用属于引用手头对象的类型(即具有相同名称),则可以通过此引用访问整个对象。否则你只能访问引用类型可以看到的对象的那些部分。

在您的示例中,引用类型为A,即obj仅查看其引用的任何对象的A部分。因此,虽然对象具有这些行为,但它无法访问对象的B / C部分。

答案 7 :(得分:0)

其他人已经回复了此问题,但请注意,有一种方法可以在不转发shutUp()B的情况下致电C

A obj = new B();
try {
    Method shutUp = obj.getClass().getMethod("shutUp", null);
    shutUp.invoke(obj, null);
}
catch (Exception ignored) {}

答案 8 :(得分:0)

A obj = new B();

在这里,您要创建“B”的实例,其类型为“A”。 即你说“我想制作一个物体B并将其命名为obj,它是A型”。

在A类中,只有一种方法可以访问。它没有实现C

public void speak() {}

为了能够访问B类的所有方法,你应该创建一个类型为“B”的“B”实例

B obj2 = new B();

这样您就可以访问

 public void shutUp() {}

这是因为它是实现类“C”的B。

使用“obj”访问这两种方法的一种方法是制作A工具C

答案 9 :(得分:0)

new B()创建的对象可以用作三种类型之一的对象 - A,B或C.但是您不能声明几种类型的变量。

由于B是A和C的子类型,因此您可以将其实例用作任何类型的实例。 E.g。

B o = new B();
A aO = o;
C cO = o;

现在,您可以使用o访问speakshutUp方法,您可以使用aO访问speak方法和cO访问shutUp方法。无论你使用哪个变量,调用的方法都是相同的,因为这些变量都引用同一个对象。为什么你不能使用aO在Java中调用shutUp是因为你已经使用没有这种方法的类型声明了你的变量。虽然你知道这个特定的对象确实有这种方法一般不会这样做。

class D extends A {
    public void speak(){
        System.out.println("Class D");
    }
}

List<A> as = new ArrayList<A>();
as.add(new A());
as.add(new B());
as.add(new D());

A a0 = as.get(0);
A a1 = as.get(1);
A a2 = as.get(2);

a0.speak(); // >> Class A
a1.speak(); // >> Class B
a2.speak(); // >> Class D 

现在,在此示例中,您在单个集合中具有三个不同类的实例。当你传递这个集合或修改它时,你永远不会知道每个对象实际上是哪个类。你所知道的是它们都是A型,它们保证属于那种类型,但实际上它们可以是A的任何子类型(如B或D)。

答案 10 :(得分:0)

通过说A obj = new B();您将代码与特定的接口实现分离。所以obj将无法访问在b类中实现的shutup()函数。