实现接口和对象

3
当一个类实现了一个接口,是否意味着从该类实例化的对象被视为该接口的对象?
例如,当一个类实现了Runnable接口时,从该类创建的实例被称为Runnable对象吗?
因此,在需要Runnable对象引用变量的地方(例如,在方法或构造函数的参数中),为什么我们可以将该类的实例作为参数提供给该方法或构造函数呢?这是因为通过实现接口,该类本质上是接口的一个对象吗?
5个回答

5
一个实现接口 I 的类 C 的对象可以被称为该接口的对象,尽管单个对象可以是许多接口中的一个。Liskov替换原则 要求 C 可以在需要 I 的任何地方使用,因此本质上,I 成为 C 的一个 合同,代表适用于某种情况下的 C 能力的子集。
例如,当一个对象实现了 Runnable 接口时,在接口中的 run() 方法向 Java 类库呈现了类的特定方面 - 即,可以通过调用 run() 在它们上面运行类的对象。有了 Runnable,你可以独立于 Java 设计者编写线程执行代码,而这些设计者则独立于你的实现逻辑编写他们自己的代码。

谢谢。所以只是确认一下,当一个接口作为方法的参数时,如果一个特定的类在类体内实现了该接口,那么你可以将关键字“this”作为参数传递给该方法?也就是说,这仅仅是因为“this”(它指的是调用该方法的对象)包含了接口的实现方法? - 151SoBad
@151SoBad:“[...]你可以将关键字this作为方法的参数传递?” 这是正确的。“这只能生效,因为this [...] 包含了接口实现的方法?”一个类可以包含接口中的所有方法,而无需实现该接口(例如,因为作者忘记写 implements XyzInterface)。在这种情况下,仅具有所有方法是不够的:需要声明该类为接口的实现,并承诺实现所有接口方法。 - Sergey Kalinichenko

2

对于 Runnable 的引用是可能的,因为 Runnable 对象必须实现 Runnable 接口中的所有方法。

这样你就可以在运行时访问所有这些方法。

如果被称为实现 Runnable 的类没有实现 Runnable,则会出现编译错误,因为 Java Language Specification 7 chapter 8 (classes) - 8.1.5 (superinterfaces) 指定:

一个类被认为实现了它的所有超级接口。

给出的示例如下:

Example 8.1.5-3. Implementing Methods of a Superinterface

interface Colorable {
    void setColor(int color);
    int getColor();
}

class Point { int x, y; };

class ColoredPoint extends Point implements Colorable {
    int color;
}

这个程序会导致编译时错误,因为ColoredPoint不是一个抽象类,但是它没有提供接口Colorable中setColor和getColor方法的实现。

2
如果一个类实现了一个接口,那么它可以在任何可以使用该接口类型的地方使用。例如,如果一个类实现了Runnable接口,那么该类的实例可以在任何可以使用Runnable的地方使用。这就是多态的一个例子。
例如,下面是一个实现了Runnable接口的类:
public class MyRunner implements Runnable {
  public void run() {}
}

您可以按照以下方式使用MyRunner
MyRunner runner = new MyRunner();

// can assign to a field of type "Runnable" without a cast
Runnable runnable = runner;

// can pass to methods that take a Runnable
Executors.newFixedThreadPool(3).execute(runner); 

MyRunner类被称为Runnable的实例。你甚至可以通过反射来检查这一点;

public void runIfIsRunnable(Object object) {
  if (object instanceof Runnable) {
    Runnable r = (Runnable) object;
    r.run();
  }
}

使用 instanceof 经常被认为是代码异味,但有些情况下它还是很有用的,比如当你通过反射创建类的实例时。


1

对象继承其父类接口,并且子类可以覆盖这些接口中的方法。

接口的价值在于它们允许创建适用于各种对象类别的方法,通过接受接口类型作为输入。

实现接口的任何对象实际上都可以针对其实现的给定接口进行“接口化”。

类实现接口意味着该类能够执行接口中指定的任何方法。因此,在接口上运行的任何方法都可以在实现接口的对象上运行。


0
接口(Interface)建立了一个契约,即对象将包含接口中定义的方法,并且这个契约由编译器强制执行。因此,编译器会对此进行检查。
按照惯例,以“-ible”或“-able”结尾的接口表示具备相应行为(尽管这并不是硬性规定)。但最终,对象的类型要么是`java.lang.Object`,要么是它的直接/间接扩展。如果你查看任何Javadoc上的继承树,你会看到类之间互相扩展,并且已知实现接口的类。
因此,我们通常不会将由类创建的对象称为接口的对象,而是说该类“实现”了某个接口。

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