在我的一次采访中,我被要求解释接口类和抽象类之间的区别。
以下是我的回答:
Methods of a Java interface are implicitly abstract
and cannot have implementations. A Java abstract class can have
instance methods that implements a default behaviour.
Variables declared in a Java interface are by default final. An
abstract class may contain non-final variables.
Members of a Java interface are public by default. A Java abstract
class can have the usual flavours of class members like private,
protected, etc.
A Java interface should be implemented using keyword “implements”; A
Java abstract class should be extended using keyword “extends”.
An interface can extend another Java interface only, an abstract class
can extend another Java class and implement multiple Java interfaces.
A Java class can implement multiple interfaces but it can extend only
one abstract class.
然而,面试官并不满意,他告诉我这种描述代表了“书本知识”。
他让我给出一个更实际的回答,用实际的例子解释我什么时候会选择抽象类而不是接口。
我哪里错了?
接口是一个“契约”,其中实现契约的类承诺实现方法。举个例子,当我将一款游戏从2D升级到3D时,我不得不编写一个界面而不是类。我必须创建一个界面来共享2D和3D版本的游戏类别。
package adventure;
import java.awt.*;
public interface Playable {
public void playSound(String s);
public Image loadPicture(String s);
}
然后我可以实现基于环境的方法,同时仍然能够从一个不知道正在加载的游戏版本的对象调用这些方法。
公共类Adventure扩展了JFrame实现了Playable
公共类Dungeon3D扩展了SimpleApplication实现的Playable
公共类Main扩展了SimpleApplication实现了AnimEventListener
ActionListener,播放
通常,在游戏世界中,世界可以是一个抽象类,在游戏中执行方法:
public abstract class World...
public Playable owner;
public Playable getOwner() {
return owner;
}
public void setOwner(Playable owner) {
this.owner = owner;
}
我先给大家举个例子:
public interface LoginAuth{
public String encryptPassword(String pass);
public void checkDBforUser();
}
假设您的应用程序中有3个数据库。然后,该数据库的每个实现都需要定义上述2个方法:
public class DBMySQL implements LoginAuth{
// Needs to implement both methods
}
public class DBOracle implements LoginAuth{
// Needs to implement both methods
}
public class DBAbc implements LoginAuth{
// Needs to implement both methods
}
但是,如果encryptPassword()不依赖于数据库,并且对每个类都是相同的呢?那么上面的方法就不是一个好的方法。
相反,考虑以下方法:
public abstract class LoginAuth{
public String encryptPassword(String pass){
// Implement the same default behavior here
// that is shared by all subclasses.
}
// Each subclass needs to provide their own implementation of this only:
public abstract void checkDBforUser();
}
现在,在每个子类中,我们只需要实现一个方法——依赖于数据库的方法。