【问题标题】:How to call parent function from instance of child?如何从子实例调用父函数?
【发布时间】:2012-08-03 10:26:09
【问题描述】:

我有模特

BaseUser.class.php
User.class.php
UserTable.class.php

在用户类中 我已经覆盖了删除功能

class User extends BaseUser {
   function delete(){
    }
}

现在,如果我想调用父删除函数....怎么办?

示例

$user = new User();
$user->delete();  // will call the overridden delete
$user-> ??  ;     // want to call parent delete

【问题讨论】:

  • 你试过$user->parent::delete();吗?
  • 是的,我试过了,但没用.... netbeans 将其显示为错误的语义
  • 当你在浏览器中运行代码时会怎样?
  • 不要忘记:您的 IDE 只是一个有用的工具。这不是“有效代码识别”的全部和全部。换句话说,有时它会产生误报。
  • 看看@j0k 的回答。它几乎涵盖了您询问的所有内容。

标签: php doctrine


【解决方案1】:

从技术上讲,这在“外部”(公共界面)是不可能的。

如果您了解原因(否则请阅读下文),并且您确实知道自己在做什么,那么没有理由不提供该功能:

class User extends BaseUser {
   ... 
   function parentDelete(){
       parent::delete();
   }
   ...
}

user = new User();
$user->delete();  // will call the overridden delete
$user->parentDelete();     // want to call parent delete

但是,如果您曾经这样做过,您应该知道您以某种方式滥用了继承。这一定是一种特殊情况,因为我无法想象在任何情况下您实际上都需要这样做。

因此,请尝试阐明您需要该功能的原因,以便为自己提供更好的建议。

为什么这么糟糕?

原因很简单:在您的软件中,您不需要知道$user 是否有父级。这是一些你根本不应该关心的细节。

这将允许您稍后将软件中的任何用户对象替换为用户的子对象。这很重要,因为您希望随着时间的推移更改您的软件。

如果您将内部细节作为公共界面的一部分,您就是在剥夺自己保持灵活性的可能性。不灵活真的很糟糕。

【讨论】:

  • 我不同意“坏”的说法。就像接口描述对象方法的签名一样,当您implement 那个接口时,当您extend 一个父对象时,您应该应该非常了解该父对象实现了什么。这是对象扩展的关键。这里没有“坏”。 EXCEPT:需要调用两个单独的方法的想法。只需将User:delete() 调用parent::delete() 作为其方法的一部分。 7 岁... 为什么我还要打扰... 大声笑
  • 是的,扩展的那个需要知道,但是那个类型的“用户”不能知道任何内部细节(只是公共接口)。很可能我的英语不是很精确,但是您的评论与我想在那个“坏”部分中说的方向一致,我也许也应该提供一个很好的例子,在里面调用 parent::delete()扩展类的 delete() 方法 - 错误就是答案,它就在上面。
  • 我自己的用例是这样的:我有一个 Mail() 类,现在我想要一个 DelayedMail() 类来fake 发送邮件,但实际上在一个数据库。伪造是通过覆盖 send() 方法来完成的。排队的最简单方法是使实例休眠并存储其表示。那里没有问题!但后来,在一个 cron 作业中,我解冻了这些对象,现在想要真正发送它们——那时我不能使用 send(),因为这会使它们重新排队。我需要使用 parent 的 发送(我称之为“actualSend()”)。我不认为这是对 OOP 的滥用,而是相反。
【解决方案2】:

不妨试试这个

parent::delete();

【讨论】:

  • 我有用户 $user 的对象如何调用这个对象?
  • 你必须在子方法中调用父方法
  • @HUGO:你不能。从外面看,两者是一样的。不是两个,而是一个对象。这就是继承的目的。
【解决方案3】:

我认为您正在寻找 PHP parent 函数:

<?php
class A {
    function example() {
    echo "I am A::example() and provide basic functionality.<br />\n";
    }
}

class B extends A {
    function example() {
    echo "I am B::example() and provide additional functionality.<br />\n";
    parent::example();
    }
}

$b = new B;

// This will call B::example(), which will in turn call A::example().
$b->example();
?>

如果您的类没有名为 getMyFunction() 的函数,则调用 $b-&gt;getMyFuction() 将调用父函数。如果是,它会调用子函数,除非子函数调用了 prent 函数。

【讨论】:

  • 我认为 OP 需要知道$b-&gt;parent::example(); 是否有效。
  • @HUGO $b>example() 将执行如下:如果子类中没有example(),则父类将执行。如果子进程中有函数example(),则会改为执行。
【解决方案4】:

如果需要调用一次父级,为什么需要扩展delete

为什么不创建自定义删除?

喜欢:

public function customDelete()
{
  parent::delete();

  // do extends delete here
}

然后你可以使用-&gt;customDelete()删除一个对象,你也可以从父级调用de​​lete方法,因为你没有覆盖delete()方法:

$user = new User();
$user->customDelete();  // will call the overridden delete
$user->delete(); // will call the parent (since you didn't override it)

如果你真的需要重写delete()函数,你仍然可以创建一种父删除:

public function parentDelete()
{
  return parent::delete();
}

然后:

$user = new User();
$user->delete();  // will call the overridden delete
$user->parentDelete(); // will call the method that only call the parent

【讨论】:

  • 这是解决原始发布者试图解决的关键问题的最佳答案:公开继承类的自定义和非自定义功能,将子类视为包装器(被知道父接口如何工作的东西使用),而不是在不知道父结构的情况下使用的不透明的新类。
【解决方案5】:

可以使用call_user_func 来完成。是的,这是不好的做法,但有可能。

class BaseUser {
    public function delete()
    {
        echo 'BaseUser deleted';
    }
}

class User extends BaseUser{
    public function delete()
    {
        echo 'User deleted';
    }
}

$instance = new User();

call_user_func(array($instance, 'parent::delete'));

结果:

BaseUser deleted

【讨论】:

    【解决方案6】:

    我在编码论坛上找到了this thread。它所说的(我倾向于同意他们的观点)是,如果您在子类中有重写的函数/方法,则该对象的实例将始终调用子方法。

    parent 关键字类似于$thisself,只能从类本身中调用。

    如果你想让一个子对象能够调用父方法,只需创建另一个方法

    function parentExample() { 
        parent::example(); 
    }
    

    只调用父方法。

    【讨论】:

      猜你喜欢
      • 2021-08-28
      • 1970-01-01
      • 1970-01-01
      • 2016-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多