PHP вызов метода родительского класса

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';

Более-менее тот же вопрос, что и stackoverflow.com/questions/16471076/… (короче нет)

iainn 22.05.2018 15:33

@iainn лучший ответ - если действительно нет встроенного решения

l00k 22.05.2018 15:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
2
79
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Это не совсем то, что я бы назвал красивым, но это работает и относительно похоже на то, что вы описали для 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'

См. этот фрагмент, чтобы увидеть это в действии.

РЕДАКТИРОВАТЬ

Это большая работа, но вы можете использовать так называемый Поздняя статическая привязка, возможно, более четко объясненный в Ответ Джокериуса здесь. Это требует, чтобы вы написали уйму собственного кода, что я не думаю, что это предпочтительно. В целом ответ кажется коротким: на самом деле это невозможно.

Я опубликовал самый простой код, который только могу представить. В реальном коде у меня много полей (тоже статических). Я могу копировать значения, но это не очень приятно.

l00k 22.05.2018 15:22

Ответ хороший, но, наверное, вопрос недостаточно точный.

l00k 22.05.2018 15:26

К моему удивлению, мой ответ работает на удивление хорошо. 3v4l.org/VdWVE Другие ответы здесь, вероятно, лучше, особенно Ли Бикнелл.

Loek 22.05.2018 15:32

Не совсем :( должен возвращать "foo14" - поле member должно быть сохранено

l00k 22.05.2018 15:36

Да, я думаю, именно так работает PHP. Я найду еще минуту, чтобы взглянуть на это, но Интернет, кажется, согласен с тем фактом, что вы просто не можете сделать это просто.

Loek 22.05.2018 15:37

Обновленный ответ. Кажется, это сделать довольно сложно.

Loek 22.05.2018 15:46

Не знаю, поможет ли это вам, но попробуйте добавить эту функцию в класс 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;
}

Да, я знаю такую ​​возможность. Однако мне интересно, есть ли что-то вроде приведения классов или удобства использования с классами отражения.

l00k 22.05.2018 15:32

нет, как я знаю, классового литья нет, но помимо этого вы можете сами написать функцию литья, см. обновленный ответ

Davit Huroyan 22.05.2018 15:33

Для меня это больше похоже на проблему дизайна, чем на что-либо другое. Однако, если бы я справился с этим так, чтобы было легко читать и не переосмысливая свой дизайн, я бы сделал:

<?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. Второе решение не подходит, потому что базовым классом является базовый класс фреймворка, и я не могу изменить список параметров.

l00k 22.05.2018 15:34

Комментарий к разделу редактирования: В C++ это возможно. Если мы говорим, что язык определяет наши возможности дизайна, я согласен. Я не очень хорошо говорю по-английски, чтобы объяснить, зачем мне это нужно :)

l00k 22.05.2018 15:46

Возможное и разумное - это две очень разные вещи в мире программирования. Это тот тип вещей, к которому я прибегал бы, если бы у меня было очень мало времени и мне дали бы запрос «просто сделай это». Даже в этом случае я бы сделал это с намерением реорганизовать его позже. Языковые функции могут ограничивать возможности разработки наших приложений, но они не определяют лучший / наиболее разумный дизайн.

Leigh Bicknell 22.05.2018 15:52
Ответ принят как подходящий

Если вы хотите разобраться с 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

См. https://3v4l.org/NP6j8

Вот и все. Спасибо. Я догадался, что есть какое-то решение с отражениями. Я должен согласиться, что это немного грязно, но менее грязно, чем копирование значений в объект родительского класса.

l00k 22.05.2018 17:09

Другие вопросы по теме