class Foo {
protected static $a = 1;
protected $b = 2;
public function func() { return 'foo' . static::$a . $this->b; }
}
class Bar extends Foo {
protected static $a = 3;
protected $b = 4;
public function func() { return 'bar' . static::$a . $this->b; }
}
$obj = new Bar();
$obj->func(); // returns of course 'bar34'
Есть ли в PHP возможность вызвать функцию func () из класса Foo? В C++ я бы привел $ obj к Foo и просто вызвал func ()
Bar* obj = new Bar();
Foo* obj2 = (Bar*) obj;
obj2->func(); // returns 'foo14';
@iainn лучший ответ - если действительно нет встроенного решения






Это не совсем то, что я бы назвал красивым, но это работает и относительно похоже на то, что вы описали для C++; Он работает, вызывая get_parent_class() и затем злоупотребляя способностью PHP создавать объекты из строк.
<?php
class Foo {
public function func() { echo 'foo'; }
}
class Bar extends Foo {
public function func() { echo 'bar'; }
}
$obj = new Bar();
$obj->func(); // Prints 'bar'
$parentClassString = get_parent_class($obj);
$newObj = new $parentClassString; // Gotta love PHP for magic like this
$newObj->func(); // Prints 'foo'
См. этот фрагмент, чтобы увидеть это в действии.
РЕДАКТИРОВАТЬ
Это большая работа, но вы можете использовать так называемый Поздняя статическая привязка, возможно, более четко объясненный в Ответ Джокериуса здесь. Это требует, чтобы вы написали уйму собственного кода, что я не думаю, что это предпочтительно. В целом ответ кажется коротким: на самом деле это невозможно.
Я опубликовал самый простой код, который только могу представить. В реальном коде у меня много полей (тоже статических). Я могу копировать значения, но это не очень приятно.
Ответ хороший, но, наверное, вопрос недостаточно точный.
К моему удивлению, мой ответ работает на удивление хорошо. 3v4l.org/VdWVE Другие ответы здесь, вероятно, лучше, особенно Ли Бикнелл.
Не совсем :( должен возвращать "foo14" - поле member должно быть сохранено
Да, я думаю, именно так работает PHP. Я найду еще минуту, чтобы взглянуть на это, но Интернет, кажется, согласен с тем фактом, что вы просто не можете сделать это просто.
Обновленный ответ. Кажется, это сделать довольно сложно.
Не знаю, поможет ли это вам, но попробуйте добавить эту функцию в класс Bar
public function callParent($function){
return parent::$function();
}
и позвони
echo $obj->callParent("func");
[ОБНОВЛЕНО] Также вы можете написать функцию приведения самостоятельно что-то вроде этого
public function castAs($newClass) {
$obj = new $newClass;
foreach (get_object_vars($this) as $key => $name) {
$obj->$key = $name;
}
return $obj;
}
Да, я знаю такую возможность. Однако мне интересно, есть ли что-то вроде приведения классов или удобства использования с классами отражения.
нет, как я знаю, классового литья нет, но помимо этого вы можете сами написать функцию литья, см. обновленный ответ
Для меня это больше похоже на проблему дизайна, чем на что-либо другое. Однако, если бы я справился с этим так, чтобы было легко читать и не переосмысливая свой дизайн, я бы сделал:
<?php
class Foo {
public function func() { return 'foo'; }
}
class Bar extends Foo {
public function func() { return 'bar'; }
public function parentFunc() { return parent::func(); }
}
$obj = new Bar();
$obj->parentFunc(); // returns of course 'foo'
Ответ Лука также работает, но не вызывает метод родительского объекта. Он просто вызывает метод родительского класса. Все зависит от того, какой функционал вы ищете.
Вы также можете сделать что-то вроде:
<?php
class Foo {
public function func() { return 'foo'; }
}
class Bar extends Foo {
public function func($parent = false) {
if ($parent) {
return parent::func();
}
return 'bar';
}
}
$obj = new Bar();
$obj->func(true); // returns of course 'foo'
Что похоже, но без необходимости в дополнительном методе.
Лично я считаю, что эта проблема, скорее всего, требует переосмысления дизайна кода, а не решения кодирования.
-- редактировать --
Чтобы подробнее рассказать о «переосмыслении дизайна кода», я бы спросил себя: «Зачем мне нужен объект, который имеет два метода с одинаковым именем, но с разными функциями? Разве это не задача для двух разных объектов? Проследите проблему назад, пока вы обнаружите проблему дизайна или точку, в которой необходимо принять решение о том, какой объект требуется вашей структуре.
1. Как я прокомментировал ответ @davithuroyan: Да, я знаю такую возможность. Однако мне интересно, есть ли что-то вроде приведения классов или удобства использования с классами отражения. 2. Второе решение не подходит, потому что базовым классом является базовый класс фреймворка, и я не могу изменить список параметров.
Комментарий к разделу редактирования: В C++ это возможно. Если мы говорим, что язык определяет наши возможности дизайна, я согласен. Я не очень хорошо говорю по-английски, чтобы объяснить, зачем мне это нужно :)
Возможное и разумное - это две очень разные вещи в мире программирования. Это тот тип вещей, к которому я прибегал бы, если бы у меня было очень мало времени и мне дали бы запрос «просто сделай это». Даже в этом случае я бы сделал это с намерением реорганизовать его позже. Языковые функции могут ограничивать возможности разработки наших приложений, но они не определяют лучший / наиболее разумный дизайн.
Если вы хотите разобраться с Reflection, это возможно, но я решительно утверждаю, что это не должно использоваться где-либо рядом с каким-либо производственным кодом. Если у вас есть экземпляр дочернего класса, значит, он у вас есть по какой-то причине, а если он переопределяет родительский метод, то это тоже произошло по какой-то причине.
Предполагая, что вы уже все это знаете, то с учетом отказа от ответственности это должно работать в любой удаленной последней версии PHP:
class Foo { public function func() { echo 'I am the parent'; } }
class Bar extends Foo { public function func() { echo 'I am the child'; } }
// Create instance of child class
$bar = new Bar;
// Create reflection class
$reflected = new ReflectionClass(get_class($bar));
// Get parent method
$method = $reflected->getParentClass()->getMethod('func');
// Invoke method on child object
$method->invokeArgs($bar, []);
// I am the parent
Вот и все. Спасибо. Я догадался, что есть какое-то решение с отражениями. Я должен согласиться, что это немного грязно, но менее грязно, чем копирование значений в объект родительского класса.
Более-менее тот же вопрос, что и stackoverflow.com/questions/16471076/… (короче нет)