Interface or an Abstract Class: which one to use?

2019-01-04 04:42发布

Please explain when I should use a PHP interface and when I should use an abstract class?

How I can change my abstract class in to an interface?

11条回答
老娘就宠你
2楼-- · 2019-01-04 04:54

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.

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.

查看更多
叼着烟拽天下
3楼-- · 2019-01-04 04:54

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.

<?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 
查看更多
该账号已被封号
4楼-- · 2019-01-04 04:55

Just wanted to add an example of when you may need to use both. I am currently writing a file handler bound to a database model in a general purpose ERP solution.

  • I have multiple abstract classes which handle the standard crud and also some specialty functionality like conversion and streaming for different categories of files.
  • The file access interface defines a common set of methods which are needed to get, store and delete a file.

This way, I get to have multiple templates for different files and a common set of interface methods with clear distinction. The interface gives the correct analogy to the access methods rather than what would have been with a base abstract class.

Further down the line when I will make adapters for different file storage services, this implementation will allow the interface to be used elsewhere in totally different contexts.

查看更多
我想做一个坏孩纸
5楼-- · 2019-01-04 05:01

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.

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.

Also, and I may be off base here not being a Java/C++/etc programmer, but data types can come into play here. 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:

<?php
interface TelevisionControls {};
class Remote implements TelevisionControls {};
class Spouse implements TelevisionControls {};
Spouse spouse = new Spouse();
Remote remote = new Remote();
isSameType = (bool)(remote == spouse)
查看更多
SAY GOODBYE
6楼-- · 2019-01-04 05:01

The technical differences between an abstract class and an interface are already listed in the other answers precisely. I want to add an explanation to choose between a class and an interface while writing the code for the sake of object oriented programming.

A class should represent an entity whereas an interface should represent the behavior.

Let's take an example. A computer monitor is an entity and should be represented as a class.

class Monitor{
    private int monitorNo;
}

It is designed to provide a display interface to you, so the functionality should be defined by an interface.

interface Display{
    void display();
}

There are many other things to consider as explained in the other answers, but this is the most basic thing which most of the people ignore while coding.

查看更多
Emotional °昔
7楼-- · 2019-01-04 05:05

To add to some of the already excellent answers:

  • Abstract classes let you provide some degree of implementation, interfaces are pure templates. An interface can only define functionality, it can never implement it.

  • Any class that implements the interface commits to implementing all the methods it defines or it must be declared abstract.

  • Interfaces can help to manage the fact that, like Java, PHP does not support multiple inheritance. A PHP class can only extend a single parent. However, you can make a class promise to implement as many interfaces as you want.

  • type: for each interface it implements, the class takes on the corresponding type. Because any class can implement an interface (or more interfaces), interfaces effectively join types that are otherwise unrelated.

  • a class can both extend a superclass and implement any number of interfaces:

    class SubClass extends ParentClass implements Interface1, Interface2 {
        // ...
    }
    

Please explain when I should use an interface and when I should use abstract class?

Use an interface when you need to provide only a template with no implementation what so ever, and you want to make sure any class that implements that interface will have the same methods as any other class that implements it (at least).

Use an abstract class when you want to create a foundation for other objects (a partially built class). The class that extends your abstract class will use some properties or methods defined/implemented:

<?php
// interface
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.

// abstract class
class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>

How I can change my abstract class in to an interface?

Here is a simplified case/example. Take out any implementation details out. For example, change your abstract class from:

abstract class ClassToBuildUpon {
    public function doSomething() {
          echo 'Did something.';
    }
}

to:

interface ClassToBuildUpon {
    public function doSomething();
}
查看更多
登录 后发表回答