According to PHP documentation,
Object Interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are implemented.
Hence, an interface is like a class with predefined method which still needs to be accessed with the -> symbol
However, the ArrayAccess Interface provides accessing of objects as arrays. Making it possible for an object to be accessed with both $object->property and $object["property"]
I cannot understand how the ArrayAccess makes it possible to change an object syntax. I've written out a code to try replicating the effect of just one of the ArrayAccess method but it throws an error
// Using the PHP ArrayAccess Interface
namespace A {
class myclass implements \ArrayAccess {
public function offsetExists($offset) { return true; }
public function offsetGet($offset) {
// changed behaviour
return $this->{$offset} ?? null;
}
public function offsetSet($offset, $value) {}
public function offsetUnset($offset) {}
}
$myclass = new myclass();
$myclass->access = 'Interface';
echo $myclass['access']; // "Interface"
};
//Trying to implement my own ArrayAccess Interface
namespace B {
interface MyArrayAccess {
public function offsetGet($offset);
}
class myclass implements MyArrayAccess {
public function offsetGet($offset) {
// change behaviour
return $this->{$offset} ?? null;
}
}
$myclass = new myclass();
$myclass->access = 'Interface';
echo $myclass['access']; // Fatal error: Uncaught Error: Cannot use object of type B\myclass as array
}
Please help me explain this properly. Thanks
Rather than to say that interface "change the behaviour of a class", I'd say interface makes it easy to expand a class functionality.
To understand interface, as an object-oriented programming concept, we should first understand what problem it is here to solve.
What problem was "Interface" designed to solve?
Interfaces are kind of contract. It is the way to achieve duck-typing in PHP. You need to think in the perspective of a library writer, who wants to expose functionality to others. For example,
To make sure that the library user knows that a
$personneeds to have agetName()method, you may create a classPersonthat has agetName()method. Then use Type Declaration to detect potential error when the code is parsed.Let's assume there is another library to feed things with food:
Consider this...
Now, let's say a user want to write a class
Petthat can both eat and be greet. The user don't want to write those features again just forPet.How to write
Petso bothGreeterandFeederlibrary can be used on it?Perhaps something like this?
Unfortunately, PHP DO NOT support multiple inheritance. A class can only
extendone single class. The above code is not valid. So in the current situation, user can only use either one of the libraries.Also for different thing, "name" might be a very different concept (e.g. a person might return both
$first_nameand$last_namewithgetName()). There might not be a sensible default implementation ofgetName()method in your library class to begin with.So you, as a library writer who want his / her library to be as flexible for user as possible. What can you do?
How to solve this problem with "Interface" in PHP?
Interface is declaration of method signatures. It is a shortcut to declare library requirement without a concrete class / inheritance requirement.
With interface, you may rewrite both library like so:
GreeterlibraryFeederlibraryInstead of requiring a concrete class (or parent class inheritance), a class is allowed to implement multiple interfaces. So the below
Petclass is totally valid in PHP:Now, an object of this
Petclass can work both withGreeterlibrary and theFeederlibrary.What about the
ArrayAccessinterface?The ArrayAccess interface is an interface declared not by 3rd party library writers, but by core PHP writers. Core PHP writer provides even more profound support to it.
A bit like interface we mentioned before, PHP provides feature to class that implements it. But instead of our
GreeterorFeederexamples above, core PHP provides Syntactic sugar to class that implements ArrayAccess. That means you may use cleaner code to work with classes implemented AccessAccess interface.In the official example,
If you implemented them, then instead of these:
You may use
$objwith array-like syntax to make your code shorter: