在我正确掌握接口最佳实践的过程中,我注意到了以下声明:
List<String> myList = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)
代替
ArrayList<String> myList = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)
- 要我的理解,是因为它可以让有一天你不希望实现一个ArrayList但也许另一种类型列表的情况下的灵活性.
有了这个逻辑,我建立了一个例子:
public class InterfaceTest {
public static void main(String[] args) {
PetInterface p = new Cat();
p.talk();
}
}
interface PetInterface {
public void talk();
}
class Dog implements PetInterface {
@Override
public void talk() {
System.out.println("Bark!");
}
}
class Cat implements PetInterface {
@Override
public void talk() {
System.out.println("Meow!");
}
public void batheSelf() {
System.out.println("Cat bathing");
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,我无法访问batheSelf()方法,因为它仅适用于Cat.这使我相信,我应该只从接口中声明,如果我只打算使用的接口(而不是从子类中额外的方法)声明的方法,否则我应该直接从类(在这种情况下,猫)申报.我在这个假设中是否正确?
pol*_*nts 33
当通过它们interface或a 引用对象之间存在选择时class,前者应该是首选的,但仅在存在适当的类型时才是优选的.
考虑作为一个例子.你不应该只是一味地用在preferrence到所有情况,因为这会剥夺你喜欢简单的操作,等等.StringimplementsCharSequenceCharSequenceStringtrim()toUpperCase()
但是,应该使用String仅关注其char值序列的方法,因为在这种情况下,这是适当的类型.这其实与本案的类.CharSequencereplace(CharSequence target, CharSequence replacement)String
另一个例子是java.util.regex.Pattern它的Matcher matcher(CharSequence)方法.这样就不仅Matcher可以创建,也可以创建其他所有内容.PatternStringCharSequence
在库中一个interface应该使用的地方的一个很好的例子,但不幸的是,它也可以在Matcher:它appendReplacement和appendTail方法只接受StringBuffer.StringBuilder自1.5以来,这个类已经被它的表兄弟所取代.
A StringBuilder不是a StringBuffer,所以我们不能使用前者的append…方法Matcher.但是,他们俩implementsAppendable(也在1.5中介绍).理想Matcher的append…方法应该接受任何方法Appendable,然后我们就可以使用StringBuilder,以及所有其他Appendable可用的方法!
因此,我们可以看到当适当的类型存在时,如何通过它们的接口引用对象可以是一个强大的抽象,但只有存在这些类型时.如果类型不存在,那么如果有意义,您可以考虑定义自己的类型.Cat例如,在此示例中,您可以定义interface SelfBathable.然后Cat你可以接受任何SelfBathable对象(例如a Parakeet)而不是引用a
如果创建一个新类型没有意义,那么无论如何你都可以通过它来引用它class.
如果存在适当的接口类型,则应使用接口类型声明参数,返回值和字段.如果您养成使用界面类型的习惯,您的程序将更加灵活.如果不存在适当的接口,则通过类引用对象是完全合适的.
您是正确的,但如果需要,您可以从界面投射到所需的宠物。例如:
PetInterface p = new Cat();
((Cat)p).batheSelf();
Run Code Online (Sandbox Code Playgroud)
当然,如果您尝试将宠物投射到狗身上,则无法调用 BatheSelf() 方法。它甚至无法编译。因此,为了避免出现问题,您可以采用如下方法:
public void bathe(PetInterface p){
if (p instanceof Cat) {
Cat c = (Cat) p;
c.batheSelf();
}
}
Run Code Online (Sandbox Code Playgroud)
使用时instanceof,您确保不会尝试让狗在运行时自己洗澡。这会引发错误。