创建一个引用接口的对象

11

一个引用变量可以声明为一个类类型或接口类型。如果该变量被声明为接口类型,则它可以引用实现该接口的任何类的任何对象。

根据上述语句,我已经写了一段代码来理解。如上所述,如果声明为接口类型,则它可以引用实现该接口的任何类的任何对象

但是在我的代码中,objParent.displayName()处显示了未定义的displayName()方法:

public class OverridenClass {
    public static void main(String[] args) {
        Printable objParent = new Parent();
        objParent.sysout();
        objParent.displayName();
    }
}

interface Printable {
    void sysout();
}

class Parent implements Printable {
    public void displayName() {
        System.out.println("This is Parent Name");
    }

    public void sysout() {
        System.out.println("I am Printable Interfacein Parent Class");
    }
}

我肯定是理解错了。有人能够解释一下吗?


你只能通过创建引用的接口访问定义在接口上的方法。所以在你的情况下,只有 sysout() 方法被成功调用。 - Anupam Haldkar
6个回答

10

但是在我的代码中,displayName()方法显示未定义。

没错,因为Printable接口中没有定义displayName。即使具体的类有其他额外的方法,你也只能通过声明使用该接口的变量来访问接口中定义的方法。这就是为什么你可以调用sysout,但无法调用displayName的原因。

如果你考虑下面的例子,这个原因就更加明显了:

class Bar {
    public static void foo(Printable p) {
        p.sysout();
        p.displayName();
    }
}

class Test {
    public static final void main(String[] args) {
        Bar.foo(new Parent());
    }
}

foo中的代码不能依赖于除了Printable接口之外的任何东西,因为在编译时我们不知道具体的类是什么。

接口的目的是定义可用于代码的特性,仅使用接口引用,而不考虑使用的具体类。


但在凯西·贝茨(Kathy Bates)中,如果变量声明为接口类型,则可以引用实现该接口的任何类的任何对象。他们所说的“任何实现接口的类的任何对象”究竟是什么意思? - Java Beginner
1
他们的意思是它可以持有任何实现该接口的对象,但要访问实现者中定义的其他方法,您需要将其强制转换。请参见我的回答。 - asifsid88
2
@Java初学者:它可以引用实现接口的任何对象,但它只能使用由接口定义的该对象的特性。这就是具有接口引用的整个目的:避免与任何特定的具体类耦合。 - T.J. Crowder
@T.J. Crowder - 你的意思是不需要进行强制类型转换吗? - Java Beginner
2
@Java初学者:没错,但如果你必须使用强制类型转换,那么很可能你的代码需要重构。使用接口的目的是编写符合接口标准的代码,而不依赖于具体类的特性。如果你需要使用具体类的特性,请使用该类声明变量,而不是接口。 - T.J. Crowder

4

displayName()方法显示为未定义,因为objParent被声明为类型Printable,而接口中没有这样的方法。要能够使用displayName()方法,您可以在接口Printable中声明它:

interface Printable {
    void sysout();
    void displayName();
}

在调用方法 displayName() 之前,先将 objParent 强制转换为类型 Parent

Printable objParent = new Parent();
objParent = (Parent) objParent;
objParent.displayName();

2
你需要进行类型转换才能访问Parent方法。
((Parent)objParent).displayName();

感谢回复,Eclipse建议了同样的事情。 - Java Beginner
欢迎 :) 希望能帮到您 - asifsid88
4
@JavaBeginner: 这样做没有任何意义。你可以直接将objParent声明为Parent - T.J. Crowder

1
编译器不关心运行时。就编译器而言,它会检查引用类型中是否有一个名为“display”的方法在你的接口类型中。
子类或实现类中声明的方法并不是超类/接口的一部分。因此,您不能使用超类/接口引用类型调用那些在子类中声明的方法。

0

无论方法签名位于何处,该接口的引用都不会产生任何错误。在您的示例中,您的sysout() 方法在接口中,因此接口的引用将不会出错,但是对于displayName() 方法,接口引用会出错。为此,您必须使用类引用。


0

接口基本上是打破单一继承规则的另一种方式。

通过使用接口,子类既可以继承其父类的方法,又可以被强制实现其接口方法。从而得到易于扩展和维护的继承树等。

然而,问题在于当子类在父类下引用时,您只能访问父类的方法。要访问接口方法,您需要将子类强制转换或创建为接口引用类型。

接口还允许收集不同家族的多个类在接口类型下进行收集。我尚未发现其好处。

在我看来,这是毫无意义的,因为我仍然无法通过仅使用父引用类型并仍然访问接口实现来实现完全的多态性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接