接口和抽象类之间到底有什么区别?
当前回答
当您想在继承层次结构中提供多态行为时,请使用抽象类。
当您想要完全无关的类的多态行为时,请使用接口。
其他回答
实际上并不是最初问题的答案,但一旦你找到了它们之间的区别的答案,你就会进入何时使用每一个困境:何时使用接口或抽象类?何时同时使用两者?
我对OOP的了解有限,但将接口视为语法中形容词的等价物对我来说一直有效(如果这个方法是假的,请纠正我!)。例如,接口名称类似于可以赋予类的属性或功能,并且类可以具有许多属性或功能:ISerializable、ICountable、IList、ICacheable、IHappy。。。
接口
接口是一个契约:编写接口的人说,“嘿,我接受这样的东西”,而使用接口的人则说“好的,我编写的类是这样的”。
接口是一个空壳。只有方法的签名,这意味着方法没有主体。接口无法执行任何操作。这只是一种模式。
例如(伪代码):
// I say all motor vehicles should look like this:
interface MotorVehicle
{
void run();
int getFuel();
}
// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{
int fuel;
void run()
{
print("Wrroooooooom");
}
int getFuel()
{
return this.fuel;
}
}
实现一个接口只消耗很少的CPU,因为它不是一个类,只是一堆名称,因此不需要进行任何昂贵的查找。在重要的时候,比如在嵌入式设备中,这是非常棒的。
抽象类
与接口不同,抽象类是类。它们的使用成本更高,因为从它们继承时需要进行查找。
抽象类看起来很像接口,但它们有更多:您可以为它们定义行为。这更像是一个人说,“这些课程应该看起来像那样,而且它们有共同点,所以填空吧!”。
例如:
// I say all motor vehicles should look like this:
abstract class MotorVehicle
{
int fuel;
// They ALL have fuel, so lets implement this for everybody.
int getFuel()
{
return this.fuel;
}
// That can be very different, force them to provide their
// own implementation.
abstract void run();
}
// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
void run()
{
print("Wrroooooooom");
}
}
实施
虽然抽象类和接口被认为是不同的概念,但实现有时会使该语句不真实。有时,他们甚至不是你想象的那样。
在Java中,这个规则是强制执行的,而在PHP中,接口是没有声明方法的抽象类。
在Python中,抽象类更多地是一种编程技巧,您可以从ABC模块中获得,并且实际上使用元类,因此使用类。接口与这种语言中的duck类型更为相关,它混合了约定和调用描述符的特殊方法(__method__方法)。
与编程一样,还有另一种语言的理论、实践和实践:-)
当您想在继承层次结构中提供多态行为时,请使用抽象类。
当您想要完全无关的类的多态行为时,请使用接口。
抽象类和接口的一般思想是由使用这些通用“设置”(某种模板)的其他类(不能单独构建)来扩展/实现,这使得为以后扩展它的所有对象设置特定的通用行为变得简单。
抽象类具有常规方法集和抽象方法。扩展类在被抽象类扩展后可以包括未设置的方法。当设置抽象方法时,它们由稍后扩展抽象方法的类定义。
接口与抽象类具有相同的财产,但只包含抽象方法,这些方法可以在其他类中实现(可以是多个要实现的接口),这就创建了一个更持久的方法/静态变量定义。与抽象类不同,您不能添加自定义的“常规”方法。
如果您有一些可供多个类使用的通用方法,请使用抽象类。否则,如果你想让类遵循某种明确的蓝图,就去寻找接口。
以下示例演示了这一点。
Java中的抽象类:
abstract class Animals
{
// They all love to eat. So let's implement them for everybody
void eat()
{
System.out.println("Eating...");
}
// The make different sounds. They will provide their own implementation.
abstract void sound();
}
class Dog extends Animals
{
void sound()
{
System.out.println("Woof Woof");
}
}
class Cat extends Animals
{
void sound()
{
System.out.println("Meoww");
}
}
以下是Java中接口的实现:
interface Shape
{
void display();
double area();
}
class Rectangle implements Shape
{
int length, width;
Rectangle(int length, int width)
{
this.length = length;
this.width = width;
}
@Override
public void display()
{
System.out.println("****\n* *\n* *\n****");
}
@Override
public double area()
{
return (double)(length*width);
}
}
class Circle implements Shape
{
double pi = 3.14;
int radius;
Circle(int radius)
{
this.radius = radius;
}
@Override
public void display()
{
System.out.println("O"); // :P
}
@Override
public double area()
{
return (double)((pi*radius*radius)/2);
}
}
简而言之,一些重要的要点:
默认情况下,Java接口中声明的变量是final。抽象类可以有非final变量。默认情况下,Java接口中声明的变量是静态的。抽象类可以具有非静态变量。默认情况下,Java接口的成员是公共的。Java抽象类可以具有类成员的通常风格,如private、protected等。。