I'm trying to understand how using interfaces gives me multiple inheritance as I've been googling.
class A
{
function do1(){}
function do2(){}
function do3(){}
}
class B extends A
{
function do4(){}
function do5(){}
function do6(){}
}
class C extends B
{
}
In the above example, class C has all the methods from class A and B. However, class B also has all the methods of class A, which is not necessary desired.
My searches have come up to use interfaces to solve this issue by moving methods to a class and creating interfaces, as below.
interface A
{
function do1();
function do2();
function do3();
}
interface B
{
function do4();
function do5();
function do6();
}
class C implements A, B
{
function do1(){}
function do2(){}
function do3(){}
function do4(){}
function do5(){}
function do6(){}
}
I don't really see how this solves the issue because all the code is in the new class. If I just wanted to use class A as originally, I would have to create a new class that implement interface A and copy the same code to the new class.
Is there something I'm missing?
Java allows multiple inheritance using interfaces. Interfaces could only define abstract methods, that is, methods without any implementation. So if a class implemented multiple interfaces with the same method signature, it was not a problem.
Classes may implement more than one interface if desired by separating each interface with a comma. A class can implement two interfaces which define a method with the same name, only if the method declaration in both interfaces is identical.
PHP programming language doesn't even support the multiple inheritance/inheritances. PHP supports multiple inheritances only by using interfaces or Traits in PHP instead of classes so that we can implement it. Traits are a type of class that enables multiple case classes, objects, classes, and traits.
Extending multiple interfaces is allowed. It just fails if the same method is declared in two or more of them.
PHP doesn't have multiple inheritance. If you have PHP 5.4, though, you can use traits to at least avoid every class having to copy code.
interface A {
public function do1();
public function do2();
public function do3();
}
trait Alike {
public function do1() { }
public function do2() { }
public function do3() { }
}
interface B {
public function do4();
public function do5();
public function do6();
}
trait Blike {
public function do4() { }
public function do5() { }
public function do6() { }
}
class C implements A, B {
use Alike, Blike;
}
class D implements A {
use Alike;
// You can even "override" methods defined in a trait
public function do2() { }
}
Note, though, you have to both implement the interface and use the trait (or, of course, provide your own implementation). And C and D are not related at all, except in both implementing the A interface. Traits are basically just interpreter-level copy and paste, and do not affect inheritance.
The first thing to understand about interfaces is that they are NOT used for inheritance. That is a very important thing to understand. If you're trying to make several classes share the same concrete code, that is not what an interface is for.
The second thing to understand is the difference between client code, and service code.
Client code is essentially the "last step" in a sequence of requests for data. A controller or a view in MVC can be considered client code. The model, meanwhile can be considered service code.
Interfaces are intended for client code to enforce consistency in the types of data it gets from services. Or another way to think about it - interfaces are a way for services to make sure they will be compatible with a request from client code. That is ALL they do. They quite literally provide an interface by which data is accessed, not an implementation that multiple classes can share.
So to give you a concrete example:
Client Code - a ProfileViewController class for a user's forum profile
class ProfileViewController
{
public function showProfile(User $user)
{
$user->getProfile();
}
}
Service Code - a User model that retrieves data and passes it on to the client code that is requesting it
class User
{
public function getProfile()
{
$profile = Do some SQL query here or something
return $profile;
}
}
Now suppose later on you decide to break up Users into Members, Administrators, Referees, Moderators, Writers, Editors etc, and that each has their own unique type of profile. (e.g. its own custom query, or data, or what have you)
There are now two problems present here:
1 is easy to solve through abstract classes and methods (or through Interfaces). 2 at first sounds easy as well, because you can just make Moderators, Admins, and Members all subclasses of a User base class.
But then what happens when down the road, in addition to USER profiles, you want to have generic profiles for things. Perhaps you want to show profiles of sports players, or even profiles of celebrities. They're not users, but they still have profiles/details pages.
Because they're not users, it may not make any sense to consider them subclasses of User.
So now you're a bit stuck. showProfile() needs to be able to accept more than just a User object. In fact, you don't know what type of object you will ultimately want to pass in there. But at the same time, since you always want to be able to grab $user->getProfile(), anything you pass in there must be generic enough to be passed in, AND implement a concrete getProfile() method.
Solution? Interfaces!!!!!
First some service code
// First define an interface for ANY service object that will have a profile
interface IHasProfile
{
public function getProfile();
}
// Next, define the class for an object that should have a profile. I'll do a bunch for the sake of an example...
class User implements IHasProfile
{
public function getProfile()
{
$profile = Your unique user profile query here
return $profile;
}
}
class Celebrity implements IHasProfile
{
public function getProfile()
{
$profile = Your unique celebrity profile query here
return $profile;
}
}
class Car implements IHasProfile
{
public function getProfile()
{
$profile = Your unique vehicle profile query goes here
return $profile;
}
}
Next, the client code that will use it
class ProfileViewController
{
public function showProfile(IHasProfile $obj)
{
$obj->getProfile();
}
}
And there you have it. showProfile() has now been abstracted enough that it doesn't care what object it gets, it only cares that the object has a public getProfile() method. So now you can create new types of objects to your heart's content, and if they are intended to have profiles, you can just give them "implements IHasProfile" and they will automatically just work with showProfile().
Kind of a contrived example, but it should illustrate at least the concept of interfaces.
Of course, you could just be "lazy" and not typecast the object at all, and thus allowing ANY object to be passed in. But that's a separate topic entirely ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With