接口或抽象类:使用哪一个?

本文翻译自:Interface or an Abstract Class: which one to use?

Please explain when I should use a PHP interface and when I should use an abstract class ? 请解释我何时应该使用PHP interface以及什么时候应该使用abstract class

How I can change my abstract class in to an interface ? 如何将abstract class更改为interface


#1楼

参考:https://stackoom.com/question/7c7J/接口或抽象类-使用哪一个


#2楼

Why to use abstract classes? 为什么要使用抽象类? The following is a simple example. 以下是一个简单的例子。 Lets say we have the following code: 可以说我们有以下代码:

<?php 

class Fruit {
    private $color;

    public function eat() {
        // chew
    }

    public function setColor($c) {
        $this->color = $c;
    }
}

class Apple extends Fruit {
    public function eat() {
        // chew until core
    }
}

class Orange extends Fruit {
    public function eat() {
        // peeling
        // chew
    }
}

Now I give you an apple and you eat it. 现在我给你一个苹果然后吃它。 What does it taste like? 尝起来怎么样? It tastes like an apple. 它的味道像苹果。

<?php 
$apple = new Apple();
$apple->eat();

// Now I give you a fruit.
$fruit = new Fruit();
$fruit->eat();

What does that taste like? 这味道是什么样的? Well, it doesn't make much sense, so you shouldn't be able to do that. 嗯,它没有多大意义,所以你不应该这样做。 This is accomplished by making the Fruit class abstract as well as the eat method inside of it. 这是通过使Fruit类抽象以及其中的eat方法来实现的。

<?php 
abstract class Fruit {
    private $color;

    abstract public function eat(){}

    public function setColor($c) {
        $this->color = $c;
    }
}
?>

An abstract class is just like an interface, but you can define methods in an abstract class whereas in an interface they are all abstract. 抽象类就像一个接口,但您可以在抽象类中定义方法,而在接口中它们都是抽象的。 Abstract classes can have both empty and working/concrete methods. 抽象类可以同时具有空和工作/具体方法。 In interfaces, functions defined there cannot have a body. 在接口中,那里定义的函数不能有一个体。 In abstract classes, they can. 在抽象类中,他们可以。

A real world example: 一个现实世界的例子:

<?php 
abstract class person {

    public $LastName;
    public $FirstName;
    public $BirthDate;

    abstract protected function write_info();
}

final class employee extends person{

    public $EmployeeNumber;
    public $DateHired;

    public function write_info(){
        //sql codes here
        echo "Writing ". $this->LastName . "'s info to emloyee dbase table <br>";   
    }
}

final class student extends person{

    public $StudentNumber;
    public $CourseName;

    public function write_info(){
        //sql codes here
        echo "Writing ". $this->LastName . "'s info to student dbase table <br>";
    }
}

///----------
$personA = new employee;
$personB = new student;

$personA->FirstName="Joe";
$personA->LastName="Sbody";

$personB->FirstName="Ben";
$personB->LastName="Dover";

$personA->write_info();
// Writing Sbody's info to emloyee dbase table
$personB->write_info();
// Writing Dover's info to student dbase table 

#3楼

Just to throw this into the mix, but as Cletus mentioned using an interface in conjunction with an abstract class, I often use the interface to clarify my design thinking. 只是把它放到混合中,但正如Cletus提到的将接口与抽象类结合使用时,我经常使用界面来阐明我的设计思维。

For instance: 例如:

<?php
class parser implements parserDecoratorPattern {
    //...
}

That way, anyone reading my code (and who knows what a Decorator Pattern is) will know right away a) how I build my parser and b) be able to see what methods are used to implement the decorator pattern. 这样,任何阅读我的代码的人(以及谁知道Decorator模式是什么)都会马上知道a)我如何构建我的解析器和b)能够看到用于实现装饰器模式的方法。

Also, and I may be off base here not being a Java/C++/etc programmer, but data types can come into play here. 此外,我可能不在这里不是Java / C ++ / etc程序员,但数据类型可以在这里发挥作用。 Your objects are of a type, and when you pass them around the type matters programmatically. 您的对象属于某种类型,当您以类型方式传递它们时会以编程方式进行操作。 Moving your contractable items into the interface only dictates the types that the methods return, but not the base type of the class that implements it. 将可契约项移动到接口中只会指示方法返回的类型,而不是实现它的类的基类型。

It's late and I can't think of a better psudo-code example, but here goes: 现在已经很晚了,我想不出更好的psudo代码示例,但是这里有:

<?php
interface TelevisionControls {};
class Remote implements TelevisionControls {};
class Spouse implements TelevisionControls {};
Spouse spouse = new Spouse();
Remote remote = new Remote();
isSameType = (bool)(remote == spouse)

#4楼

Best practice is to use an interface to specify the contract and an abstract class as just one implementation thereof. 最佳实践是使用接口来指定合同,并使用抽象类作为其一个实现。 That abstract class can fill in a lot of the boilerplate so you can create an implementation by just overriding what you need to or want to without forcing you to use a particular implementation. 该抽象类可以填充很多样板文件,因此您可以通过覆盖您需要或想要的内容来创建实现,而不必强制您使用特定的实现。


#5楼

The main difference is an abstract class can contain default implementation whereas an interface cannot. 主要区别在于抽象类可以包含默认实现,而接口则不能。

An interface is a contract of behaviour without any implementation. 接口是行为契约,没有任何实现。


#6楼

Use an interface when you want to force developers working in your system (yourself included) to implement a set number of methods on the classes they'll be building. 如果要强制在系统中工作的开发人员(包括您自己)在他们将要构建的类上实现一定数量的方法,请使用接口。

Use an abstract class when you want to force developers working in your system (yourself included) to implement a set numbers of methods and you want to provide some base methods that will help them develop their child classes. 如果要强制在系统中工作的开发人员(包括您自己)实现一定数量的方法, 并且希望提供一些有助于他们开发子类的基本方法,请使用抽象类。

Another thing to keep in mind is client classes can only extend one abstract class, whereas they can implement multiple interfaces. 要记住的另一件事是客户端类只能扩展一个抽象类,而它们可以实现多个接口。 So, if you're defining your behavior contracts in abstract classes, that means each child class may only conform to a single contract. 因此,如果您在抽象类中定义行为合同,则意味着每个子类可能只符合单个合同。 Sometimes this a good thing, when you want to force your user-programmers along a particular path. 有时这是一件好事,当你想强迫你的用户程序员沿着特定的路径行进时。 Other times it would be bad. 其他时候会很糟糕。 Imagine if PHP's Countable and Iterator interfaces were abstract classes instead of interfaces. 想象一下,如果PHP的Countable和Iterator接口是抽象类而不是接口。

One approach that's common when you're uncertain which way to go (as mentioned by cletus below ) is to create an interface, and then have your abstract class implement that interface. 当您不确定要走哪条路时(如下面cletus所述 ),一种常见的方法是创建一个接口,然后让您的抽象类实现该接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值