это php ошибка: подклассы должны объявить закрытые методы с той же подписью как в родительском классе

Я использую php 5.3, и да, существует ошибка, открытая для этого, но некоторые думают, что это не ошибка, и это заставляет меня задаться вопросом.

abstract class A{
   private function bobo(array $in){
     //do something
   }
}

class B extends A{
   private function bobo($shmoo,$shmaa){
     //do something
   }
}

Это бросает ошибку. Разве наследование не должно игнорировать закрытые методы?!

'Объявление B:: bobo () должен быть совместим с тем из A:: bobo ()'

6
задан Gordon 15 July 2010 в 19:12
поделиться

5 ответов

Я думаю, здесь есть две возможности. Либо это ошибка, либо документация на PHP.net/manual неверна. Вот три раздела руководства по PHP.Сначала о наследовании:

Наследование объектов

Наследование - это хорошо зарекомендовавший себя принцип программирования, и PHP делает использование этого принципа в своем объекте модель. Этот принцип повлияет на как многие классы и объекты относятся к друг друга.

Например, когда вы расширяете класс, подкласс наследует все общедоступные и защищенные методы из родительский класс. Если класс не отменяет эти методы, они сохранят свои оригинальный функционал.

Это полезно для определения и абстрагирование функциональности и разрешений реализация дополнительных функциональность в похожих объектах без необходимости заново реализовывать все общая функциональность.

И об абстрактных классах:

Абстракция класса

PHP 5 вводит абстрактные классы и методы. Не допускается создание экземпляра класса, который был определен как абстрактный. Любой класс, содержащий хотя бы один абстрактный метод также должен быть абстрактным. Методы, определенные как абстрактные, просто объявляют сигнатуру метода они не могут определить реализацию.

При наследовании от абстрактного класса все методы, помеченные как абстрактные в родительском классе объявление класса должно быть определено дочерним элементом; кроме того, эти методы должны быть определены с такой же (или менее ограниченной) видимостью. Например, если аннотация метод определен как защищенный, реализация функции должна быть определена как защищенный или общедоступный, но не частный.

Наконец, интерфейсы

Интерфейсы объектов

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

Интерфейсы определяются с помощью ключевого слова interface так же, как и стандартный класс, но без какого-либо из методов, для которых определено их содержимое.

Все методы, объявленные в интерфейсе, должны быть общедоступными, такова природа интерфейса.

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

Это мое мнение ...

2
ответ дан 16 December 2019 в 21:33
поделиться

Я полагаю, что это дизайнерское решение языка. Разработчики языка Java решили, что это должно быть возможно.

0
ответ дан 16 December 2019 в 21:33
поделиться

В отчете об ошибке при удалении интерфейса ошибки нет. Это делает его "более" странным поведением, потому что интерфейс просто пустой.

1
ответ дан 16 December 2019 в 21:33
поделиться

Обратите внимание, что сообщение об ошибке немного не соответствует действительности, так как PHP выводит это сообщение при любом уровне ошибки E_STRICT (или, в последнее время, независимо от уровня ошибки при условии, что вы установили пользовательский обработчик ошибок).

Правила видимости PHP ясно показывают, что ребенок не имеет возможности видеть приватные члены своего родителя, что вряд ли кого-то удивит. Если ребенок не может видеть методы своего родителя, я не понимаю, как он может быть обязан подчиняться их определениям.

Я лично думаю, что пометка ошибки как фиктивной без объяснения того, почему она не является настоящим недостатком (поскольку она неочевидна, и я не нашёл упоминания о ней в документации), немного неправильна, но да. Кроме того, я считаю, что строка 2669 в zend_compile.c должна читаться так:

} else if (child->prototype &&
    (EG(error_reporting) & E_STRICT || EG(user_error_handler))) {

...что позволило бы избежать появления ошибки, когда родительский метод помечен как private. Учитывая, что у вас всегда есть возможность не регистрировать E_STRICT, и это ни на что не влияет, я полагаю, что это не очень важно. Я определенно не понимаю, как это могло быть сделано намеренно, но я также не разработчик PHP-движков.

5
ответ дан 16 December 2019 в 21:33
поделиться

Частные методы, конечно же, не должны игнорироваться наследованием, рассмотрим, например, шаблон метода шаблона, в котором вы можете переопределить поведение функции в производном классе, но родительский класс по-прежнему может вызывать эту функцию

public class Parent {
    public final function doThings() {
        $this->initialize();
        $this->customStuff();
        $this->cleanup();
    }

    private final function initialize() {
        // initialize processing
    }

    private final function cleanup() {
        // cleanup processing
    }

    private function customStuff() {
        // parent specific processing
    }
}

public class Derived extends Parent {
    private function customStuff() {
        parent::customStuff();
        // + derived class specific processing
    }
}

Вызов метода doThings в экземпляре производного класса будет выполнять специфичную для родительского класса обработку, но из-за возможности переопределить частные методы все еще можно воспользоваться точкой расширения, предоставляемой методом customStuff неокончательного родительского класса.

РЕДАКТИРОВАТЬ: Также подпись метода PHP состоит только из имени метода, поскольку вы можете определить метод, принимающий нулевые параметры, и при этом вызывать его с несколькими параметрами. Затем функция может получить доступ к аргументам с помощью функции func_get_args.

0
ответ дан 16 December 2019 в 21:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: