Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-从接口类型而不是类声明_Java_Interface - Fatal编程技术网

Java-从接口类型而不是类声明

Java-从接口类型而不是类声明,java,interface,Java,Interface,在我正确掌握界面最佳实践的过程中,我注意到如下声明: List<String> myList = new ArrayList<String>(); 我的问题是,我无法访问batherself()方法,因为它只存在于Cat中。这让我相信,如果我只使用在接口中声明的方法(而不是子类中的额外方法),那么我应该只从接口声明,否则我应该直接从类中声明(在本例中是Cat)。我的假设正确吗?是的,你是正确的。您应该声明为提供所使用方法的最通用类型 这就是多态性的概念。是的,你是对的。

在我正确掌握界面最佳实践的过程中,我注意到如下声明:

List<String> myList = new ArrayList<String>();

我的问题是,我无法访问batherself()方法,因为它只存在于Cat中。这让我相信,如果我只使用在接口中声明的方法(而不是子类中的额外方法),那么我应该只从接口声明,否则我应该直接从类中声明(在本例中是Cat)。我的假设正确吗?

是的,你是正确的。您应该声明为提供所使用方法的最通用类型


这就是多态性的概念。

是的,你是对的。通过让Cat实现“PetInterface”,您可以在上面的示例中使用它,并轻松添加更多种类的宠物。如果你真的需要特定于猫,你需要访问猫类。

你的答案是正确的,但是如果你需要,你可以从界面转换到所需的宠物。例如:

PetInterface p = new Cat();
((Cat)p).batheSelf();
当然,如果你想把宠物扔给狗,你不能调用batherself()方法。它甚至不会编译。因此,为了避免出现问题,您可以采用如下方法:

public void bathe(PetInterface p){
    if (p instanceof Cat) {
        Cat c = (Cat) p;
        c.batheSelf();
    }
}

使用
instanceof
时,请确保在运行时不会让狗自己洗澡。这将抛出一个错误。

您可以从Cat中的
talk
调用方法
batherself

在通过其
接口引用对象或
类引用对象之间进行选择时,应首选前者,但前提是存在适当的类型

实现
为例。对于所有情况,您都不应该盲目地使用
CharSequence
而不是
String
,因为这会拒绝像
trim()
toUpperCase()等简单操作

但是,如果一个方法只使用
字符串
来关心它的
char
值序列,那么应该使用
CharSequence
,因为在这种情况下,这是合适的类型。实际上,
String
类中的情况就是这样

另一个例子是它的设计和方法。这允许从
模式
创建一个
匹配器
,不仅用于
字符串
,还用于所有其他
字符序列

库中的一个很好的例子是,应该使用
接口,但不幸的是没有,也可以在中找到:its和方法仅接受。自1.5版以来,这个类基本上被它的更快的同类所取代

StringBuilder
不是
StringBuffer
,因此我们不能将前者与
Matcher
中的
append…
方法一起使用。但是,它们都实现了
(也在1.5中介绍)。理想情况下,
Matcher
append…
方法应该接受任何
appendeable
,然后我们就可以使用
StringBuilder
,以及所有其他可用的
appendeable

因此,我们可以看到,当一个适当的类型存在时,通过接口引用对象是一个强大的抽象,但前提是这些类型存在。如果该类型不存在,那么如果有意义的话,可以考虑定义自己的类型。例如,在此
Cat
示例中,您可以定义
接口自浴池。然后,您可以接受任何
可自洗澡的
对象(例如
长尾鹦鹉
),而不是参考

如果创建一个新类型没有意义,那么您可以通过它的
类来引用它

另见
  • 有效Java第二版,第52项:通过对象接口引用对象 如果存在适当的接口类型,则应使用接口类型声明参数、返回值和字段。如果你养成了使用接口类型的习惯,你的程序将会更加灵活。如果不存在合适的接口,那么由类引用对象是完全合适的

相关链接

通常,您应该更喜欢接口而不是具体的类。沿着这些思路,如果您可以避免使用新操作符(在新的ArrayList示例中,它总是需要具体的类型),那就更好了

这一切都与管理代码中的依赖项有关。最好只依赖于高度抽象的东西(如接口),因为它们往往非常稳定(请参阅)。因为它们没有代码,所以只有在API改变时才需要改变它们……换句话说,当您希望该接口向世界呈现不同的行为时,即设计改变时

另一方面,课程总是在变化。依赖于类的代码不关心它如何做它所做的事情,只要API的输入和输出不改变,调用方就不应该关心

您应该根据开闭原则(请参阅)努力确定类的行为,这样即使在添加功能时,现有接口也不需要更改,您只需指定一个新的子接口即可

避免新操作符的旧方法是使用抽象工厂模式,但这会带来一系列问题。更好的方法是使用像Guice这样的工具进行依赖项注入,并且更喜欢构造函数注入。在开始使用依赖项注入之前,请确保您了解依赖项反转原则(请参阅)。我见过很多人注入了不适当的依赖项,后来又抱怨这个工具没有帮助他们……它不会让你成为一个优秀的程序员,你仍然必须正确地使用它

你正在写一个帮助学生学习物理的程序。在本课程中,学生可以在各种物理场景中放置球,并观察球的行为:从悬崖上的大炮中射出球,将球放在水下,放在深空中,等等。问题:你想包括一些关于
PetInterface p = new Cat();
((Cat)p).batheSelf();
public void bathe(PetInterface p){
    if (p instanceof Cat) {
        Cat c = (Cat) p;
        c.batheSelf();
    }
}
Cat c = new Cat();
PetInterface p = (PetInterface)c;
p.talk();
c.batheSelf();