3

请通过下面给出的代码,它来自 php 手册

<?php
class A {
    private function foo() {
        echo "success!\n";
    }
    public function test() {
        $this->foo();
        static::foo();
    }
}

class B extends A {
   /* foo() will be copied to B, hence its scope will still be A and
    * the call be successful */
}

class C extends A {
    private function foo() {
        /* original method is replaced; the scope of the new one is C */
    }
}

$b = new B();
$b->test();
$c = new C();
$c->test();   //fails
?> 

谁能解释这里到底发生了什么?

为什么 foo() 会被复制到 B ?

4

2 回答 2

4

我现在记得为什么后期静态绑定很有用。不幸的是,php.net 的例子解释得不好。请参阅此(修改后的)示例:

<?php
class A {
    private function foo() {
        echo __CLASS__;
    }
    public function test() {
        $this->foo();
        static::foo();
    }
}

class B extends A {
    public function foo()
    {
        echo __CLASS__;
    }
}

$b = new B();
$b->test();
?>

如果你运行上面的代码,你会发现它可以工作,你会得到AB. 为什么?

  • 它之所以有效,是因为它test()是一个公共的getter foo(),所以无论你test()是从一个类型A的对象还是从一个B继承自的类型的对象调用都没有关系A,因为test()总是可以访问它所在的类的私有成员。定义。
  • 在第一种情况下$this->foo();总是会调用A::foo(),因为绑定是在本地完成的,在A's 范围内,这有时是非常不可取的。看到这个评论:http ://www.php.net/manual/en/language.oop5.late-static-bindings.php#83502
  • 在第二种情况下,static::foo();指示解释器确定$b's 类型并查看在哪个类中尝试查找foo()。在这种情况下,被B::foo()视为.A::foo()B::foo()A::foo()
  • 尝试标记B::foo()为私有并运行我提供的示例,看看会发生什么。我认为这个测试和我上面的咆哮会为你澄清这个问题;)

另外,我接受对以上几点的任何评论,因为我已经有一段时间没有使用 PHP 了。

于 2012-06-17T16:09:24.417 回答
2

foo本身并没有复制到 B (它是继承的但不可见;请参阅下面的 Gordon 评论)。B 继承A->foo,它调用A->test. 为了演示,看看当你echo __CLASS__从内部testfoo(并删除static::foo()导致错误的调用)时会发生什么:

class A {
    private function foo() {
        echo __CLASS__."->foo\n";
        echo "success!\n";
    }
    public function test() {
        echo __CLASS__."->test\n";
        $this->foo();
    }
}

输出:

A->test
A->foo
success!
A->test
A->foo
success!

这是继承的基础之一,因为它与信息隐藏/封装有关。这使您可以执行以下操作:

class ListOfThings {
    // internal structure (top secret!)
    private $_list = array();

    // add item to list
    public function add($item) {
        $this->_list[] = $item;
    }

    // return number of items in list
    public function count() {
        return count($this->_list);
    }
}

class ListOfStates extends ListOfThings {

    // do we have all 50 states?
    public function allStatesListed() {
        return $this->count() === 50;
    }

    // try to access internal structure of ListOfThings
    public function accessInternalStructure() {
        sort($this->_list);
    }
}

$states = new ListOfStates;
$states->add('ME');
$states->add('NH');
$states->add('VT');
$states->add('RI');
$states->add('CT');
var_dump($states->count());
var_dump($states->allStatesListed());
$states->accessInternalStructure();

输出:

int(5)
bool(false)

Warning: sort() expects parameter 1 to be array, null given...

如您所见,ListOfStates能够使用 的所有公共功能ListOfThings,即使这些功能都依赖于私有变量$_list。也就是说,ListOfStates不能直接操纵$_list;它只能$_list通过中定义的公共功能间接起作用ListOfThings

查看PHP 文档中的Visibility页面以获取有关此类内容的更多详细信息。

于 2012-06-17T15:37:38.500 回答