странное поведение php oop, кто-то может объяснить? - PullRequest
2 голосов
/ 27 мая 2011

В двух словах: класс наследует функцию от своего родителя.Затем эта функция вызывается для дочернего элемента, но, похоже, все еще имеет область действия parent класса.Это ожидаемое поведение?

Рассмотрим следующий пример кода:

<?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

Фактический вывод на моей машинеis:

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

Чтобы добавить к путанице, print_r($this) в любой из функций покажет, что область действия действительно установлена ​​на подкласс, но доступ к переменной невозможен.

Может кто-нибудь прояснить это для меня?

РЕДАКТИРОВАТЬ: я использую PHP в версии 5.3.3-1ubuntu9.5.

Ответы [ 6 ]

4 голосов
/ 27 мая 2011

Нет, выходной сигнал обязательно должен быть 10, undefined, 10, undefined.Причина в том, что переменные private видны только определяющему их классу (не супер или подклассам).

Таким образом, когда вызывается child, его методы определяются в родительском объекте икогда они разрешают var1 или var2, они проверяют область, определенную для OLTest.var2 также недоступен, поскольку объявленный var2 виден только внутри OLTest2.

Чтобы получить вывод, вы должны объявить эти переменные protected или public.

2 голосов
/ 27 мая 2011

Да, это потому, что ваши свойства являются частными. Методы, которые вы вызываете, все еще принадлежат родительскому классу, так как вы не переопределили их. Чтобы разрешить родительским методам доступ к дочерним свойствам, вы должны сделать их 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() также не будет работать).

2 голосов
/ 27 мая 2011

Похоже, это связано с областью действия private.

Попробуйте изменить на protected или public и проверьте результаты.

1 голос
/ 27 мая 2011

Поскольку вы объявили свои переменные закрытыми, они полностью скрыты друг от друга.Таким образом, $var1 в родительском элементе фактически отличается от $var1 в дочернем элементе

. Когда вы вызываете getVar1 для родительского элемента, он использует $var1, который видитparent со значением 10. Аналогично родитель не может видеть дочерний элемент $var2, поэтому для него свойство не определено.

Когда вы вызываете getVar1 и getVar2 для дочернего элемента, сами методы наследуютсяиз родительского класса и ведут себя точно так же, как если бы они были вызваны из объекта типа OLTest

1 голос
/ 27 мая 2011

Вы не можете "внедрить" private $var2 в родительский класс, что вы и пытались сделать.Так что да, это нормальное поведение.

0 голосов
/ 27 мая 2011

Это область ваших личных переменных, попробуйте использовать защищенный

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...