奇怪的php oop行为,有人可以解释一下吗?

时间:2011-05-27 14:31:57

标签: php oop inheritance

简而言之:一个类从其父级继承一个函数。然后在子项上调用此函数,但似乎仍具有类的范围。这是预期的行为吗?

请考虑以下代码示例:

<?php
class OLTest {
    private $var1 = 10;

    public function getVar1() {
        if (isset($this->var1)) {
            return $this->var1;
        } else {
            return 'undefined';
        }
    }

    public function getVar2() {
        if (isset($this->var2)) {
            return $this->var2;
        } else {
            return 'undefined';
        }
    }
}

class OLTest2 extends OLTest {
    private $var1 = 11;
    private $var2 = 20;
}

$oltest = new OLTest();
$oltest2 = new OLTest2();

echo "calling parent->getVar1\n";
echo $oltest->getVar1() . "\n";

echo "calling parent->getVar2\n";
echo $oltest->getVar2() . "\n";

echo "calling child->getVar1\n";
echo $oltest2->getVar1() . "\n";

echo "calling child->getVar2\n";
echo $oltest2->getVar2() . "\n";
?>

根据我的理解,输出应为:

calling parent->getVar1
10
calling parent->getVar2
undefined
calling child->getVar1
11
calling child->getVar2
20

我机器上的实际输出是:

calling parent->getVar1
10
calling parent->getVar2
undefined
calling child->getVar1
10
calling child->getVar2
undefined

为了增加混淆,任何一个函数中的print_r($this)都会显示范围确实设置为子类,但是无法访问变量。

有人可以为我清楚吗?

编辑:我在版本5.3.3-1ubuntu9.5中使用PHP。

6 个答案:

答案 0 :(得分:4)

不,输出应该是10, undefined, 10, undefined。 原因是private变量只对定义它们的类(不是超类或子类)可见。

因此,当调用child时,其方法在父对象中定义,当他们解析var1var2时,他们会检查为OLTest定义的范围。 var2也无法访问,因为声明的var2仅在OLTest2内可见。

要获得输出,您应该声明这些变量protectedpublic

答案 1 :(得分:2)

它似乎与private范围相关。

尝试更改为protectedpublic并检查结果。

答案 2 :(得分:2)

是的,这是因为您的属性是私有的。您正在调用的方法仍属于父类,因为您尚未重新定义它们。要启用访问子属性的父方法,必须在父类和子类中使它们protected

class OLTest {
    protected $var1 = 10;

    public function getVar1() {
        if (isset($this->var1)) {
            return $this->var1;
        } else {
            return 'undefined';
        }
    }

    public function getVar2() {
        if (isset($this->var2)) {
            return $this->var2;
        } else {
            return 'undefined';
        }
    }
}

class OLTest2 extends OLTest {
    protected $var1 = 11;
    protected $var2 = 20;
}

如果将它private保留在父类中,它将不允许子类覆盖该属性,因此属于父类的函数将访问其自己的私有属性。如果你在子类中将其设为私有,则不允许父方法访问它。

如果您仍想将它们保密,则必须将方法的代码复制粘贴到子类中(是的,return parent::getVar1()也不会有效。)

答案 3 :(得分:1)

您不能将private $var2“注入”父类,这是您尝试做的事情。 所以是的,这是正常行为。

答案 4 :(得分:1)

因为您已将您的vars声明为私有,所以它们彼此完全隐藏。因此,父级中的$var1实际上是与子级中的$var1不同的变量

当您在父级上调用getVar1时,它会使用它看到的$var1,父级的值为10.同样,父级无法看到孩子的$var2,所以财产未定义。

当您在子节点上调用getVar1getVar2时,方法本身将从父类继承,并且行为与从OLTest类型的对象调用它们时的行为完全相同

答案 5 :(得分:0)

这是私有变量的范围,请尝试使用protected

class OLTest {
    protected $var1 = 10;

    public function getVar1() {
        return isset($this->var1) ? $this->var1:'undefined';
    }

    public function getVar2() {
        return isset($this->var2) ? $this->var2:'undefined';
    }
}

class OLTest2 extends OLTest {
    protected $var1 = 11;
    protected $var2 = 20;
}

$oltest  = new OLTest();
$oltest2 = new OLTest2();

echo "calling parent->getVar1\n".$oltest->getVar1()."\n";
echo "calling parent->getVar2\n".$oltest->getVar2()."\n";
echo "calling child->getVar1\n".$oltest2->getVar1()."\n";
echo "calling child->getVar2\n".$oltest2->getVar2()."\n";

结果:

calling parent->getVar1
10
calling parent->getVar2
undefined
calling child->getVar1
11
calling child->getVar2
20