假设有两个java类。
BaseA
public class BaseA extends ModuleBase{
public void doSomething{
//does something
}
}
BaseB
public class BaseB extends ModuleBase implements
SomeInterface {
public void doSomething{
//does something
}
}
SomeInterface
public interface SomeInterface {
public void doSomething();
}
因此您可以看到BaseA
&之间的唯一区别BaseB
是BaseB
实现接口。据我所知,接口是一个类似于类的引用类型,它只能包含常量,方法签名,默认方法,静态方法和嵌套类型。它无法实例化。
问题:
BaseA
& BaseA
与方法&它们中的代码是一样的。正确的吗?BaseB
强制实施doSomething
,与BaseA
一样,其可选&不会产生编译错误。如果没有,那么为什么?implements InterfaceName
Vs BaseB
中所见的关键字BaseA
也可以实现,我们实现了完全相同的doSomething()
}。在类声明中有关键字implements InterfaceName
有什么不同?答案 0 :(得分:2)
没有。当Java中的类具有相同的完全限定名称并且从同一个类加载器加载时,它们是相同的。 Java不会尝试查看方法,也不会比较方法签名。
或者换句话说:Java不支持duck typing。
通常,接口用于使一堆类可以轻松互换。所以你有一些需要某种功能的东西。您可以使用界面,而不是将其键入单个类。然后,使用该服务的人可以根据他们的需要为其提供不同的课程,使服务更加灵活(并且有点难以理解)。
这意味着您可以在预期BaseB
的任何地方使用InterfaceName
。这使BaseB
(以及从中派生的所有内容)更有用/更强大。
示例:
如果要检查密码,可以编写PasswordService
课程。但这意味着每个人都必须使用这个课程并忍受限制。
如果你提供PasswordService
接口,那么代码的用户可以有不同的实现:他们可以从文件,数据库,LDAP,...获取密码,或者对于单元测试,他们可以编写服务对每个密码都说是或否。
答案 1 :(得分:1)
关键字在类声明中实现InterfaceName有什么不同?
然后您可以转换到该界面。
Java不是鸭子型。
即使您的班级方法void run()
类似于Runnable
,您仍然无法在不实施界面的情况下将其提供给需要Runnable
的地方。
new Thread(instanceOfMyNotRunnableClass); // won't compile
答案 2 :(得分:1)
两个类的代码不相同。代码可能相同但类仍然不同。具有相同代码的两个类可能表现相似但不相同。
要理解Interface的目的,您应该了解抽象和封装的概念。接口不仅提供契约,还提供对底层类的抽象。您可以编写一个接受Interface类型对象的API,而不必担心实现接口的实际类。
您可以在BaseName中使用BaseB但不应该使用。这使得您的代码只能使用BaseB,而您可以编写一个实用程序来获取已实现该接口的任何类。
答案 3 :(得分:0)
好吧,我假设SomeInterface声明" doSomething",对吧?
如果是这种情况,那么您可以将BaseB视为SomeInterface。假设你有另一个类BaseC,它也实现了SomeInterface,那么这段代码是有效的:
SomeInterface inter = new BaseB();
inter = new BaseC();
虽然这是无效的:
SomeInterface interr = new BaseA();
你的优点是,你不必知道,如果inter是BaseB()或BaseC(),因为你只需简单地处理接口声明的方法,无论执行方式如何。
答案 4 :(得分:0)
接口用于制作API的骨架。与java.util.ArrayList和java.util.LinkedList类似,它们都是实现接口java.util.List的类。
所以如果你有类似下面的方法
void doSomething(java.util.List list){
}
您可以根据您的要求传递java.util.ArrayList或java.util.LinkedList而不会造成任何伤害。您不必创建两个diff。一个接受java.util.ArrayList而另一个接受java.util.LinkedList
的方法