Это ошибка PHP: подклассы должны объявлять частные методы с той же сигнатурой, что и в родительском классе - PullRequest
6 голосов
/ 15 июля 2010

Я использую 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 ()'

Ответы [ 5 ]

5 голосов
/ 16 июля 2010

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

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

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

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

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

2 голосов
/ 16 июля 2010

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

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

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

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

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

А на абстрактных классах:

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

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

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

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

Объектные интерфейсы

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

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

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

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

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

1 голос
/ 16 июля 2010

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

0 голосов
/ 15 июля 2010

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

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 для экземпляра класса Derived будет выполнять обработку, специфичную для родительского объекта, но из-за возможности переопределения закрытых методов все еще можно воспользоваться преимуществами точки расширения, предоставленной неконечным методом родительского класса customStuff.

EDITТакже сигнатура метода PHP состоит только из имени метода, поскольку вы можете определить метод, принимающий нулевые параметры, и при этом вызывать его с несколькими параметрами.Затем функция может получить доступ к аргументам с помощью функции func_get_args.

0 голосов
/ 15 июля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...