ChatGPT解决这个技术问题 Extra ChatGPT

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?

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


D
Darryl Hein

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.


I was trying all day to understand the usages of abstract and interface classes, your post made it all clear. Thanks a lot Alan
Another advantage of abstract classes is the ability to define abstract protected methods. Not always useful, but can come in handy in some architectures.
So in many cases we should use abstract class because of flexibility - that's my conclusion :)
@volocuga : not necessarily, like Alan pointed out, only a single abstract can be extended. I personally don't like the abstract implements an interface idea because it contributes to code obfuscation and is less direct, IMO.
D
Darryl Hein

The differences between an Abstract Class and an Interface:

Abstract Classes

An abstract class can provide some functionality and leave the rest for derived class.

The derived class may or may not override the concrete functions defined in the base class.

A child class extended from an abstract class should logically be related.

Interface

An interface cannot contain any functionality. It only contains definitions of the methods.

The derived class MUST provide code for all the methods defined in the interface.

Completely different and non-related classes can be logically grouped together using an interface.


Can you provide a real life example to demonstrate it?
Whats the difference between abstract class X implements Y and class X implements Y ?
@Webinan In abstract class X implements Y you declare that the bulk functionality of X should be implemented in a derived class and that both the abstract and derived class must contain functions defined in Y, while class X implements Y only implies that class X must contain functions defined in Y. If your interface Y is not intended to be implemented by any other class than X I would actually skip defining Y as an interface and only implement the functions in Y as public/protected/private abstract function to make sure they are implemented in the deriving class.
Interfaces can not only contain definition of methods, they also can contain constants
Liked your comparison. So wanted to add something. Interfaces can have class constants out of the box while abstract class can not.
a
alexandre-rousseau

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 

Hi, this answer probably got downvotes due to the way in which it is formatted. It would be good if it wasn't a big code block (four spaces make something into a code block, unindent the text to take it out of the block), and if this was copy-pasted from somewhere (it looks like so) it would be polite to credit them.
I love you for the fruit example man ! Since i started learning php, This exmaples makes me clear thanks alot
+1 What does that taste like? Well, it doesn't make much sense, so you shouldn't be able to do that. Now I know abstract!
What does the final keyword do? Great post, thanks.
@VineeshKalarickal What I don't understand in the Person example is the difference between: 1) using the abstract class Person (as in the example); 2) writing Person as a standard class and making Employee and Student override the write_info() method.
c
cletus

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.


a
alexandre-rousseau

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)

What an awesome example! ;)
@matt2000 Not sexist AND works for same-sex marriages now too. Great edit. :)
This is an awesome example! However, I don't think you can instantiate an abstract class but rather a class that extends from an abstract class
wouldn't kill to make the sudo-code at least look like the language in question. someone should put some $'s in there.
While the example is funny, we cannot instantiate an abstract class directly, please make changes in the example so that people might not consider it to be valid usage in PHP.
T
Thielicious

Also, just would like to add here that just because any other OO language has some kind of interfaces and abstraction too doesn't mean they have the same meaning and purpose as in PHP. The use of abstraction/interfaces is slightly different while interfaces in PHP actually don't have a real function. They merely are used for semantic and scheme-related reasons. The point is to have a project as much flexible as possible, expandable and safe for future extensions regardless whether the developer later on has a totally different plan of use or not.

If your English is not native you might lookup what Abstraction and Interfaces actually are. And look for synonyms too.

And this might help you as a metaphor:

INTERFACE

Let's say, you bake a new sort of cake with strawberries and you made up a recipe describing the ingredients and steps. Only you know why it's tasting so well and your guests like it. Then you decide to publish your recipe so other people can try that cake as well.

The point here is

- to make it right - to be careful - to prevent things which could go bad (like too much strawberries or something) - to keep it easy for the people who try it out - to tell you how long is what to do (like stiring) - to tell which things you CAN do but don't HAVE to

Exactly THIS is what describes interfaces. It is a guide, a set of instructions which observe the content of the recipe. Same as if you would create a project in PHP and you want to provide the code on GitHub or with your mates or whatever. An interface is what people can do and what you should not. Rules that hold it - if you disobey one, the entire construct will be broken.

ABSTRACTION

To continue with this metaphor here... imagine, you are the guest this time eating that cake. Then you are trying that cake using the recipe now. But you want to add new ingredients or change/skip the steps described in the recipe. So what comes next? Plan a different version of that cake. This time with black berries and not straw berries and more vanilla cream...yummy.

This is what you could consider an extension of the original cake. You basically do an abstraction of it by creating a new recipe because it's a lil different. It has a few new steps and other ingredients. However, the black berry version has some parts you took over from the original - these are the base steps that every kind of that cake must have. Like ingredients just as milk - That is what every derived class has.

Now you want to exchange ingredients and steps and these MUST be defined in the new version of that cake. These are abstract methods which have to be defined for the new cake, because there should be a fruit in the cake but which? So you take the black berries this time. Done.

There you go, you have extended the cake, followed the interface and abstracted steps and ingredients from it.


This has been my favorite comparison of anything PHP related. It really made sense. Thank you!
M
Mitch Wheat

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.


w
worldofjr

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();
}

I
IEatBagels

From a phylosophic point of view :

An abstract class represents an "is a" relationship. Lets say I have fruits, well I would have a Fruit abstract class that shares common responsabilities and common behavior.

An interface represents a "should do" relationship. An interface, in my opinion (which is the opinion of a junior dev), should be named by an action, or something close to an action, (Sorry, can't find the word, I'm not an english native speaker) lets say IEatable. You know it can be eaten, but you don't know what you eat.

From a coding point of view :

If your objects have duplicated code, it is an indication that they have common behavior, which means you might need an abstract class to reuse the code, which you cannot do with an interface.

Another difference is that an object can implement as many interfaces as you need, but you can only have one abstract class because of the "diamond problem" (check out here to know why! http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem)

I probably forget some points, but I hope it can clarify things.

PS : The "is a"/"should do" is brought by Vivek Vermani's answer, I didn't mean to steal his answer, just to reuse the terms because I liked them!


The word you're looking for is edible, I believe.
Actually, I believe its a "Verb", a "doing word"
P
Pang

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.


PHP doesnt define return types and the OP tagged this question with PHP
U
Umair Ahmed

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.