Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
访问父级';从父项';PHP中的上下文_Php_Class - Fatal编程技术网

访问父级';从父项';PHP中的上下文

访问父级';从父项';PHP中的上下文,php,class,Php,Class,我有一个名为ClassA的绘图PHP类,它被许多其他绘图类扩展,例如ClassB 我需要继承的类触发其父类的Draw()方法。但是,在我的特殊情况下,我不想直接调用这样的方法(例如:parent::Draw())。我想要第三个函数(例如:parent::InvokeDraw())从父级上下文中调用我的绘图方法 下面是一些代码来说明: class ClassA { function Draw() { /* Drawing code ... */ }

我有一个名为ClassA的绘图PHP类,它被许多其他绘图类扩展,例如ClassB

我需要继承的类触发其父类的Draw()方法。但是,在我的特殊情况下,我不想直接调用这样的方法(例如:
parent::Draw()
)。我想要第三个函数(例如:
parent::InvokeDraw()
)从父级上下文中调用我的绘图方法

下面是一些代码来说明:

class ClassA
{
    function Draw()
    {

        /* Drawing code ... */

    }

    function InvokeDraw()
    {
        $this->Draw();
    }
}

class ClassB extends ClassA
{
    function Draw()
    {
        parent::InvokeDraw();

        /* Drawing code ... */

    }
}
我面临的问题是InvokeDraw()不会调用父类的Draw()方法,而是调用扩展类的ownDraw()方法,从而导致无限循环

虽然这个问题相当合乎逻辑,但我很难找到解决办法。如何完成这项任务

预期效果

无限循环问题

这是一种使用静态方法的方法

<?php

class ClassA
{
    function Draw()
    {
        echo "DrawA";
        /* Drawing code ... */

    }

    function InvokeDraw()
    {
        self::Draw();
    }
}

class ClassB extends ClassA
{
    function Draw()
    {
        echo "DrawB";
        parent::InvokeDraw();

        /* Drawing code ... */

    }
}

echo "Begin:<br>";

$cb = new ClassB();
$cb->Draw();
编辑: 为了回答您下面的评论,我将添加一个关于您的代码如何工作以及此代码如何工作的简短描述

代码中发生了什么:

  • 我们创建
    B
    并开始使用它
  • B
    类和
    B
    对象中工作时,我们调用
    B->Draw()
  • B->Draw()
    静态调用(这意味着类方法)
    A::Invoke()
    从类A调用,但是我们仍然使用
    B
    对象
  • 静态调用
    A::Invoke()
    调用
    $this->Draw()
    目前我们正在处理
    B
    对象,
    $this
    引用了
    ClassB
    的一个实例
  • 现在我们开始循环
  • 在上面的代码中发生了什么:

  • 我们创建
    B
    并开始使用它
  • B
    类和
    B
    对象中工作时,我们调用
    B->Draw()
  • B->Draw()
    静态调用(这意味着类方法)
    A::从类A调用
    ,但是以及在您的代码中,我们仍然在使用
    B
    对象
  • 静态调用
    A::Invoke()
    调用
    self::Draw()
    ,这与
    ClassA::Draw()
    基本相同,因为它是一个静态方法,所以我们不关心当前使用的对象,我们调用
    A
    Draw()
    方法
  • A::Draw()
    方法根据需要执行
  • 我将在第二个答案中对代码进行相同的解释,它不使用静态调用:

    <?php
    
    class ClassA
    {
    
        function Draw()
        {
            echo "DrawA";
            /* Drawing code ... */
    
        }
    
        function InvokeDraw()
        {
            $this->Draw();
        }
    }
    
    class ClassB extends ClassA
    {
    
        function Draw()
        {
            echo "DrawB";
            $x = new parent;
            $x->InvokeDraw();
    
            /* Drawing code ... */
    
        }
    }
    
    echo "Begin:<br>";
    
    $cb = new ClassB();
    $cb->Draw();
    
  • 我们创建
    B
    并开始使用它
  • B
    类和
    B
    对象中工作时,我们调用
    B->Draw()
  • B->Draw()
    创建
    A
    的一个实例
  • B->Draw()
    调用
    A->Invoke()
    ,这意味着我们开始处理类
    A
    的实例对象,而不是像以前那样的
    B
  • 在这一点上,我们完全忘记了
    B
    甚至是存在的,并且只使用
    A

  • A->Invoke()
    调用
    $this->Draw()
    ,这意味着我们正在调用
    A->Draw()
    ,因为我们已经在处理类
    A
    的实例
  • A->Draw()
    按预期执行
  • 从可用性的角度来看,静态方法更好,因为我们可以定义一些静态属性,并且在执行
    A::Draw()
    时可以使用它们。如果我们使用非静态方法,那么我们需要在方法的参数内传递所需的数据


    我希望这能说明问题。上面的顺序没有正确的术语,但它是故意写的,我认为这样更容易理解流程。

    我非常喜欢你的问题,我做了一些研究,并尝试与我的第一个答案相同,但没有静态调用:

    <?php
    
    class ClassA
    {
    
        function Draw()
        {
            echo "DrawA";
            /* Drawing code ... */
    
        }
    
        function InvokeDraw()
        {
            $this->Draw();
        }
    }
    
    class ClassB extends ClassA
    {
    
        function Draw()
        {
            echo "DrawB";
            $x = new parent;
            $x->InvokeDraw();
    
            /* Drawing code ... */
    
        }
    }
    
    echo "Begin:<br>";
    
    $cb = new ClassB();
    $cb->Draw();
    

    从表面上看,继承就像是合并代码。继承的方法是子类的一部分,就像它们是该类的本机方法一样:

    class A {
    
        public function foo() {
            echo 'foo';
        }
    
        public function bar() {
            echo 'bar';
        }
    
    }
    
    class B extends A { }
    
    就所有意图和目的而言,这相当于书写:

    class B {
    
        public function foo() {
            echo 'foo';
        }
    
        public function bar() {
            echo 'bar';
        }
    
    }
    
    B
    具有函数
    foo
    bar
    ,就好像它们是其声明的一部分一样

    子类中的重写方法将一个特定实现替换为另一个实现:

    class B extends A {
    
        public function bar() {
            echo 'baz';
        }
    
    }
    
    这就好像
    B
    是这样声明的:

    class B {
    
        public function foo() {
            echo 'foo';
        }
    
        public function bar() {
            echo 'baz';
        }
    
    }
    
    除了一个例外:父对象的方法实现可以使用
    parent
    关键字来实现。它不会更改执行代码的上下文,只是使用父级的方法实现:

    class B extends A {
    
        public function bar() {        public function bar() {
            parent::bar();      --->       echo 'bar';
        }                              }
    
    }
    
    它在当前
    B
    实例的相同上下文中工作,它只是将父级的旧代码从以太网中拉出

    如果在父类的方法中调用另一个方法,它将在子类的上下文中执行,而不是在父类的上下文中执行。因为您没有实例化父对象,所以您正在处理子对象。要使用属性进行演示(与方法的效果相同):

    因此,你的问题没有解决办法。不能在“父上下文”中调用方法。您可以在当前上下文中调用父级的代码,仅此而已。您所创建的是一个简单的循环,因为不管代码是否被继承,它都在相同的上下文中工作


    您需要重新设计该类,以避免在循环中调用方法。

    正如deceze所说,除非重新设计该类,否则您的问题没有解决方案

    如果您使用的是PHP5.4,那么可以使用

    创建2个特征,每个特征都有自己的
    Draw
    功能。然后在父母身上使用一个特征,在孩子身上使用另一个特征

    然后,为了从子函数访问父函数,将
    InvokeDraw
    别名设置为父函数
    Drawclass B extends A {
    
        public function bar() {        public function bar() {
            parent::bar();      --->       echo 'bar';
        }                              }
    
    }
    
    class A {
    
        protected $value = 'bar';
    
        public function bar() {
            echo $this->value;
        }
    
    }
    
    class B extends A {
    
        protected $value = 'baz';
    
        public function bar() {
            parent::bar();     // outputs "baz"
            echo $this->value; // outputs "baz"
        }
    
    }
    
    <?php
    
    trait DrawingA
    {
        function Draw()
        {
            echo 'I am the parent';
        }
    }
    
    trait DrawingB
    {
        function Draw()
        {
            echo 'I am the child';
        }
    }
    
    class ClassA
    {
        use DrawingA;
    }
    
    class ClassB extends ClassA
    {
        use DrawingA, DrawingB {
            DrawingB::Draw insteadof DrawingA;
            DrawingA::Draw as InvokeDraw;
        }
    }
    
    $b = new ClassB();
    
    echo 'Child: ',  $b->Draw(), PHP_EOL;
    echo 'Parent: ', $b->InvokeDraw() . PHP_EOL;
    
    /*
    Outputs:
    
    Child: I am the child
    Parent: I am the parent
    
    */