在我的一次采访中,我被要求解释接口类和抽象类之间的区别。
以下是我的回答:
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.
然而,面试官并不满意,他告诉我这种描述代表了“书本知识”。
他让我给出一个更实际的回答,用实际的例子解释我什么时候会选择抽象类而不是接口。
我哪里错了?
这个世界上没有什么是完美的。他们可能期待的是更实际的方法。
但在你解释之后,你可以用稍微不同的方法添加这些行。
Interfaces are rules (rules because you must give an implementation to them that you can't ignore or avoid, so that they are imposed like rules) which works as a common understanding document among various teams in software development.
Interfaces give the idea what is to be done but not how it will be done. So implementation completely depends on developer by following the given rules (means given signature of methods).
Abstract classes may contain abstract declarations, concrete implementations, or both.
Abstract declarations are like rules to be followed and concrete implementations are like guidelines (you can use it as it is or you can ignore it by overriding and giving your own implementation to it).
Moreover which methods with same signature may change the behaviour in different context are provided as interface declarations as rules to implement accordingly in different contexts.
编辑:Java 8简化了在接口中定义默认方法和静态方法。
public interface SomeInterfaceOne {
void usualAbstractMethod(String inputString);
default void defaultMethod(String inputString){
System.out.println("Inside SomeInterfaceOne defaultMethod::"+inputString);
}
}
现在,当一个类将实现SomeInterface时,并不强制为interface的默认方法提供实现。
如果我们有另一个具有以下方法的接口:
public interface SomeInterfaceTwo {
void usualAbstractMethod(String inputString);
default void defaultMethod(String inputString){
System.out.println("Inside SomeInterfaceTwo defaultMethod::"+inputString);
}
}
Java不允许扩展多个类,因为这会导致“钻石问题”,即编译器无法决定使用哪个超类方法。如果使用默认方法,接口也会出现菱形问题。因为如果一个类同时实现这两个
SomeInterfaceOne and SomeInterfaceTwo
并且没有实现常见的默认方法,编译器不能决定选择哪一个。
为了避免这个问题,在java 8中必须实现不同接口的通用缺省方法。如果任何类实现了上述两个接口,它必须提供defaultMethod()方法的实现,否则编译器将抛出编译时错误。
是的,从技术上讲,你的回答是正确的,但你的错误之处在于,你没有向他们表明你理解选择其中一个的利弊。此外,他们可能担心将来升级时代码库的兼容性问题。这种类型的回答可能有帮助(除了你说的):
"Choosing an Abstract Class over an Interface Class depends on what we
project the future of the code will be.
Abstract classes allow better forward-compatibility because you can
continue adding behavior to an Abstract Class well into the future
without breaking your existing code --> this is not possible with an
Interface Class.
On the other hand, Interface Classes are more flexible than Abstract
Classes. This is because they can implement multiple interfaces. The
thing is Java does not have multiple inheritances so using abstract
classes won't let you use any other class hierarchy structure...
So, in the end a good general rule of thumb is: Prefer using Interface
Classes when there are no existing/default implementations in your
codebase. And, use Abstract Classes to preserve compatibility if you
know you will be updating your class in the future."
祝你下次面试好运!
你的回答是对的,但是面试官需要你从软件工程的角度来区分,而不是根据Java的细节。
简单的单词:
An Interface is like the interface of a shop anything that is shown on it should be there in the shop, so any method in the Interface must be there implemented in the concrete class. Now what if some classes share some exact methods and varies in others. Suppose the Interface is about a shop that contains two things and suppose we have two shops both contain sport equipment but one has clothes extra and the other has shoes extra. So what you do is making an abstract class for Sport that implements the Sports method and leave the other method unimplemented. Abstract class here means that this shop doesn't exist itself but it is the base for other classes/shops. This way you are organising the code, avoiding errors of replicating the code, unifying the code, and ensuring re-usability by some other class.
接口由单例变量(公共静态final)和公共抽象方法组成。当我们知道要做什么但不知道如何做时,我们通常更喜欢实时使用接口。
这个概念可以通过以下例子更好地理解:
考虑一个支付类。支付方式有很多种,比如PayPal,信用卡等。因此,我们通常将Payment作为接口,其中包含makePayment()方法,CreditCard和PayPal是两个实现类。
public interface Payment
{
void makePayment();//by default it is a abstract method
}
public class PayPal implements Payment
{
public void makePayment()
{
//some logic for PayPal payment
//e.g. Paypal uses username and password for payment
}
}
public class CreditCard implements Payment
{
public void makePayment()
{
//some logic for CreditCard payment
//e.g. CreditCard uses card number, date of expiry etc...
}
}
在上面的例子中,CreditCard和PayPal是两个实现类/策略。接口还允许我们在Java中实现多重继承的概念,这是抽象类无法实现的。
当我们知道某些特性该做什么,而其他特性又知道如何执行时,我们就会选择一个抽象类。
考虑下面的例子:
public abstract class Burger
{
public void packing()
{
//some logic for packing a burger
}
public abstract void price(); //price is different for different categories of burgers
}
public class VegBerger extends Burger
{
public void price()
{
//set price for a veg burger.
}
}
public class NonVegBerger extends Burger
{
public void price()
{
//set price for a non-veg burger.
}
}
如果我们将来在给定的抽象类中添加方法(具体的/抽象的),那么实现类将不需要更改其代码。但是,如果将来在接口中添加方法,则必须将实现添加到实现该接口的所有类中,否则会发生编译时错误。
还有其他不同之处,但这些都是面试官所期望的。希望这对你们有帮助。