变量作为接口名称
你没有一个接口类型的一类。 x
变量的实际(运行时)类型为Audi
,它不是接口。在运行时您可以从永远不会实例化一个接口,只有实际的类型。但是,因为你已经在编译时输入的x
变量Car
只有这个接口将被已知的,那么就可以调用仅此接口中的方法:
Car x = new Audi();
x.AMethodOnTheInterface();
你的代码将工作得很好;这是一个非常常见的成语。
您可以将变量或字段声明为接口,然后将实现接口的任何类的实例放入其中。
比如,人们经常写
List<Car> myCars = new ArrayList<Car>();
这是编程的接口,而不是常见的咨询到实施。这就是你在这里做的。这意味着x
是实现Car
的对象;也就是说,它可以完成汽车可以做的所有事情,这就是你关心的所有事情(除非你做一些演员,否则可以使用)。它的工作原理是因为奥迪始终是一辆汽车,所以您可以使用它并将其分配到任何需要汽车的地方。
这是一个常见的,并且往往是有益的事情;如果没有演员,你不必关心你的车是否真的是奥迪(并且写一大堆奥迪专用的代码,如果你的爱车除了奥迪之外都有可能是无用的)。
区别在于“声明类型”和“实施类型”之间。前者可以是后者之上的任何抽象。
在这种特殊情况下,代码声明Car
正在满足(实施)Audi
的实例。在这种情况下,将执行任何Car
的实现。
一个更明显的例子是类似Car
的公共成员。在这种情况下,该类的内部实现需要一个Car
,任何Car
,以完成某些任务。您可以将其设置为实现Car
的任何对象。
你在那里做的是编码到一个接口而不是一个实现,在可以的情况下,它是一件好事,因为它允许你在最小的难度下交换实现。这与原理相同:
List<String> strs = new ArrayList<String>();
您正在创建一个arraylist,它是实现类型,但引用是类型list。然后,对符合列表接口的对象执行所有操作 - 如果需要,可以灵活地将实现交换到链接列表或甚至是自己编码的另一个列表,而不会破坏任何其他代码(只要因为它当然是正确实施的!)
同样的原理适用于您的汽车物体。