接口和抽象类之间到底有什么区别?
当前回答
接口与抽象类的比较是错误的。应该有另外两个比较:1)接口与类,2)抽象与最终类。
接口与类
接口是两个对象之间的契约。例如,我是一名邮递员,而你是一个要递送的包裹。我希望你知道你的送货地址。当有人给我一个包裹时,它必须知道它的送货地址:
interface Package {
String address();
}
类是一组遵守契约的对象。例如,我是“箱子”小组的一名箱子,我遵守邮递员要求的合同。同时,我遵守其他合同:
class Box implements Package, Property {
@Override
String address() {
return "5th Street, New York, NY";
}
@Override
Human owner() {
// this method is part of another contract
}
}
摘要与最终
抽象类是一组不完整的对象。它们不能使用,因为它们缺少一些部件。例如,我是一个抽象的GPS感知框-我知道如何检查我在地图上的位置:
abstract class GpsBox implements Package {
@Override
public abstract String address();
protected Coordinates whereAmI() {
// connect to GPS and return my current position
}
}
这个类如果被另一个类继承/扩展,可能非常有用。但就其本身而言,它是无用的,因为它不能有对象。抽象类可以是最终类的构建元素。
Final类是一组完整的对象,可以使用,但不能修改。他们确切地知道如何工作和做什么。例如,我是一个盒子,它总是在构建过程中到达指定的地址:
final class DirectBox implements Package {
private final String to;
public DirectBox(String addr) {
this.to = addr;
}
@Override
public String address() {
return this.to;
}
}
在大多数语言中,如Java或C++,可能只有一个类,既不是抽象类也不是最终类。这样的类可以继承并实例化。不过,我认为这并不严格符合面向对象的范例。
同样,将接口与抽象类进行比较是不正确的。
其他回答
php.net上抽象类和接口的简单而有效的解释:
接口就像一个协议。它不指定对象的行为;它指定代码如何告诉该对象的动作。接口类似于英语:定义接口定义代码如何与实现该接口的任何对象通信。接口始终是一个协议或承诺。当一个类说“我实现接口Y”时,它就是说“我承诺拥有与任何具有接口Y的对象相同的公共方法”。另一方面,抽象类类似于部分构建的类。它很像是一个有空格要填写的文档。它可能使用英语,但这并不像某些文档已经写好这样重要。抽象类是另一个对象的基础。当一个类显示“I extend abstract class Y”时,它表示“I use some methods or properties already defined in this other class named Y”。因此,请考虑以下PHP:<?php文件类X实现了Y{}//这意味着“X”同意使用代码使用语言“Y”。类X扩展了Y{}//这意味着“X”将完成部分类“Y”。?>如果您正在分发一个类供其他人使用,那么您的类将实现一个特定的接口。接口是一个协议,为您的类提供一组特定的公共方法。如果您(或其他人)编写了一个已经编写了一些要在新类中使用的方法的类,则可以让您的类扩展一个抽象类。这些概念虽然很容易混淆,但却特别不同和不同。出于所有意图和目的,如果您是任何类的唯一用户,则不需要实现接口。
在实用性方面(JAVA),抽象类和接口之间的主要区别是抽象类可以保存状态。除了保持状态,我们还可以使用Interface实现其余操作。
接口通常是没有逻辑的类,只有签名。而抽象类是具有逻辑的类。两者都支持作为接口的契约,所有方法都应该在子类中实现,但在抽象中只应该实现抽象方法。何时使用接口,何时抽象?为什么使用界面?
class Circle {
protected $radius;
public function __construct($radius)
{
$this->radius = $radius
}
public function area()
{
return 3.14159 * pow(2,$this->radius); // simply pie.r2 (square);
}
}
//Our area calculator class would look like
class Areacalculator {
$protected $circle;
public function __construct(Circle $circle)
{
$this->circle = $circle;
}
public function areaCalculate()
{
return $circle->area(); //returns the circle area now
}
}
我们只需要
$areacalculator = new Areacalculator(new Circle(7));
几天后,我们将需要矩形、正方形、四边形等区域。如果是这样,我们是否必须每次更改代码并检查实例是正方形、圆形还是矩形?现在OCP所说的是接口代码而不是实现。解决方案是:
Interface Shape {
public function area(); //Defining contract for the classes
}
Class Square implements Shape {
$protected length;
public function __construct($length) {
//settter for length like we did on circle class
}
public function area()
{
//return l square for area of square
}
Class Rectangle implements Shape {
$protected length;
$protected breath;
public function __construct($length,$breath) {
//settter for length, breath like we did on circle,square class
}
public function area()
{
//return l*b for area of rectangle
}
}
现在是面积计算器
class Areacalculator {
$protected $shape;
public function __construct(Shape $shape)
{
$this->shape = $shape;
}
public function areaCalculate()
{
return $shape->area(); //returns the circle area now
}
}
$areacalculator = new Areacalculator(new Square(1));
$areacalculator->areaCalculate();
$areacalculator = new Areacalculator(new Rectangle(1,2));
$areacalculator->;areaCalculate();
这不是更灵活吗?如果我们在没有接口的情况下进行编码,我们将检查每个形状冗余代码的实例。
现在什么时候使用抽象?
Abstract Animal {
public function breathe(){
//all animals breathe inhaling o2 and exhaling co2
}
public function hungry() {
//every animals do feel hungry
}
abstract function communicate();
// different communication style some bark, some meow, human talks etc
}
现在,当一个人不需要那个类的实例,具有类似的逻辑,需要契约时,应该使用抽象。
实际上并不是最初问题的答案,但一旦你找到了它们之间的区别的答案,你就会进入何时使用每一个困境:何时使用接口或抽象类?何时同时使用两者?
我对OOP的了解有限,但将接口视为语法中形容词的等价物对我来说一直有效(如果这个方法是假的,请纠正我!)。例如,接口名称类似于可以赋予类的属性或功能,并且类可以具有许多属性或功能:ISerializable、ICountable、IList、ICacheable、IHappy。。。
抽象类和接口的一般思想是由使用这些通用“设置”(某种模板)的其他类(不能单独构建)来扩展/实现,这使得为以后扩展它的所有对象设置特定的通用行为变得简单。
抽象类具有常规方法集和抽象方法。扩展类在被抽象类扩展后可以包括未设置的方法。当设置抽象方法时,它们由稍后扩展抽象方法的类定义。
接口与抽象类具有相同的财产,但只包含抽象方法,这些方法可以在其他类中实现(可以是多个要实现的接口),这就创建了一个更持久的方法/静态变量定义。与抽象类不同,您不能添加自定义的“常规”方法。
推荐文章
- 在PHP5中创建单例设计模式
- Java抽象接口
- 什么是依赖倒置原则?为什么它很重要?
- 为什么在Python方法中需要显式地有“self”参数?
- 如何在方法中访问“静态”类变量?
- 为什么c#不提供c++风格的'friend'关键字?
- String, StringBuffer和StringBuilder
- 如何在python抽象类中创建抽象属性?
- 存储库和服务层的区别?
- DDD -实体不能直接访问存储库的规则
- 为什么STL如此严重地基于模板而不是继承?
- 如何在Objective-C中声明类级属性?
- 面向方面编程与面向对象编程
- c++中类似于java的instanceof
- 在python中遍历对象属性