tdb*_*i22 15 php oop inheritance interface
我试图理解使用接口如何给我多重继承,因为我一直在谷歌上搜索.
class A
{
function do1(){}
function do2(){}
function do3(){}
}
class B extends A
{
function do4(){}
function do5(){}
function do6(){}
}
class C extends B
{
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,类C具有来自类A和B的所有方法.但是,类B也具有类A的所有方法,这是不必要的.
我的搜索已经出现使用接口来解决这个问题,方法是将方法移动到类并创建接口,如下所示.
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(){}
}
Run Code Online (Sandbox Code Playgroud)
我真的没有看到这是如何解决这个问题的,因为所有代码都在新类中.如果我只想最初使用类A,我将不得不创建一个实现接口A的新类,并将相同的代码复制到新类.
有什么我想念的吗?
cHa*_*Hao 28
PHP没有多重继承.但是,如果您使用PHP 5.4,则可以使用特征来至少避免每个类都必须复制代码.
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() { }
}
Run Code Online (Sandbox Code Playgroud)
但请注意,您必须实现接口并使用特征(当然,还要提供您自己的实现).除了实现A接口外,C和D完全没有关系.特征基本上只是解释器级别的复制和粘贴,不会影响继承.
Agm*_*her 22
关于接口的第一件事是它们不用于继承.这是一个非常重要的事情要理解.如果你试图让几个类共享相同的具体代码,那不是一个接口的用途.
要理解的第二件事是客户端代码和服务代码之间的区别.
客户端代码本质上是数据请求序列中的"最后一步".MVC中的控制器或视图可以被视为客户端代码.同时,该模型可以被视为服务代码.
接口用于客户端代码,以强制从服务获取的数据类型的一致性.或者考虑它的另一种方式 - 接口是服务的一种方式,以确保它们与客户端代码的请求兼容.这就是他们所做的一切.它们确实提供了一个访问数据的接口,而不是多个类可以共享的实现.
所以给你一个具体的例子:
客户端代码 - 用户论坛配置文件的ProfileViewController类
class ProfileViewController
{
public function showProfile(User $user)
{
$user->getProfile();
}
}
Run Code Online (Sandbox Code Playgroud)
服务代码 - 用于检索数据并将其传递给请求数据的客户端代码的用户模型
class User
{
public function getProfile()
{
$profile = Do some SQL query here or something
return $profile;
}
}
Run Code Online (Sandbox Code Playgroud)
现在假设您稍后决定将用户分解为成员,管理员,裁判,版主,作家,编辑等,并且每个人都有自己独特的个人资料类型.(例如,它自己的自定义查询,或数据,或你有什么)
现在有两个问题:
1很容易通过抽象类和方法(或通过接口)来解决.2起初听起来也很简单,因为你可以让Moderator,Admins和Members成为User基类的所有子类.
但是接下来会发生什么,除了USER配置文件之外,你还想拥有通用的配置文件.也许你想展示体育运动员的简介,甚至是名人的简介.他们不是用户,但他们仍然有个人资料/详细信息页面.
因为它们不是用户,所以将它们视为User的子类可能没有任何意义.
所以现在你有点卡住了.showProfile()需要能够接受的不仅仅是User对象.实际上,您不知道最终想要传递的对象类型.但与此同时,由于你总是希望能够获取$ user-> getProfile(),所以你传递的任何内容都必须足够通用,并且实现一个具体的getProfile()方法.
解?接口!!!!!
首先是一些服务代码
// 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;
}
}
Run Code Online (Sandbox Code Playgroud)
接下来,将使用它的客户端代码
class ProfileViewController
{
public function showProfile(IHasProfile $obj)
{
$obj->getProfile();
}
}
Run Code Online (Sandbox Code Playgroud)
你有它.showProfile()现在已经被抽象得足够多了,它不关心它得到什么对象,它只关心对象有一个公共的getProfile()方法.所以现在你可以根据心脏内容创建新类型的对象,如果它们打算有配置文件,你可以给它们"实现IHasProfile",它们将自动只使用showProfile().
一种人为的例子,但至少应该说明接口的概念.
当然,你可能只是"懒惰"而不是对对象进行类型转换,从而允许传入任何对象.但这完全是一个单独的主题;)
多重继承仅适用于接口!
比如我的输出:
php > interface A{};
php > interface B{};
php > interface C extends A,B{};
php > class D implements C{};
php > $d = new D();
php > echo ($d instanceof A);
1
Run Code Online (Sandbox Code Playgroud)
对于 lulz,我尝试创建扩展 D 和 stdclass 类的 E 类并得到错误!
php > class E extends D, stdclass{};
PHP Parse error: syntax error, unexpected ',', expecting '{' in php shell code on line 1
Parse error: syntax error, unexpected ',', expecting '{' in php shell code on line 1
Run Code Online (Sandbox Code Playgroud)