实现接口和对象

Implementing Interfaces and Objects

当 class 实现接口时,是否会使从 class 实例化的对象被视为该接口的对象?

即在 class 实现 Runnable 接口后,是否会使从 class 创建的实例称为 Runnable 对象?

那么,在需要 Runnable 对象引用变量的地方(比如,在方法或构造函数的参数中),为什么我们可以提供 class 的实例作为参数是合法的该方法或构造函数?是不是因为实现了接口,class,本质上就是Interface的一个对象?

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

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

如果据称实现 Runnable 的 class 将以某种方式不实现 Runnable - 将出现编译错误,如 Java Language Specification 7 chapter 8 (classes) - 8.1.5 (superinterfaces) 指定:

A class is said to implement all its superinterfaces.

给出的例子如下:

示例 8.1.5-3。实现超级接口的方法

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

class Point { int x, y; };

class ColoredPoint extends Point implements Colorable {
    int color;
}

该程序导致编译时错误,因为 ColoredPoint 不是抽象的class,但未能提供接口 Colorable 的 setColor 和 getColor 方法的实现.

class C 的对象实现了一个接口 I 可以称为该接口的对象,尽管单个对象可以是多个接口。 Liskov substitution principle 要求 C 可以在任何需要 I 的地方使用,所以本质上 I 变成了 contract of C,代表 C 能力的子集,适用于特定情况。

例如,当对象实现Runnable时,接口中的run()方法呈现class到Javaclass的特定方面library - 也就是说,class 的对象可以是 "ran"(通过对它们调用 run())。 Runnable 的存在使您可以独立于 Java 设计人员编写线程逻辑代码,而设计人员编写的线程执行代码独立于您的实现逻辑。

对象继承其父 classes 接口,这些接口的方法可以在子 classes 中被覆盖。

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

任何实现接口的对象实际上"interface"能够用于它实现的给定接口。

class 接口的实现意味着 class 能够执行接口内指定的任何方法。因此,接口上 运行 的任何方法都可以 运行 实现接口的东西。

如果一个class实现了一个接口,它可以用在任何可以使用该接口类型的地方。例如,如果 class 实现了 Runnable,那么 class 的实例可以在任何可以使用 Runnable 的地方使用。这是多态性的一个例子。

例如,这里有一个 class 实现了 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 class 据说是 Runnable 的实例。您甚至可以通过反射来检查它;

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

使用 instanceof 通常被认为是一种代码味道,但在某些情况下它很有用,例如当您通过反射创建 class 的实例时。

一个接口建立了一个契约,对象将包含接口中定义的方法,这个契约由编译器强制执行。所以编译器会检查这个。

按照惯例,以“-ible”结尾的接口“能够”显示此行为(尽管这绝不是硬性规定)。但最后,对象的类型要么是 java.lang.Object 要么是它的 direct/indirect 扩展。如果您查看任何 Javadoc 上的继承树,您将看到 classes 的层次结构相互扩展并且已知实现 classes 的接口。

所以人们通常不会将 class 创建的对象称为接口的对象,而是 class 实现 的对象。