PHP. Статические методы
Объявляем класс:
{
function tellme()
{
echo 'OK';
}
}
Вызываем метод:
Результат: ОК
"Странно", думаю. Ну всякое бывает, может не углядел в документации, что по умолчанию методы считаются статическими, если не указано явно. Задаем тогда видимость.
{
public function tellme()
{
echo 'OK';
}
}
Опять вызываем как статический метод, опять работает:
Результат: ОК
В этом месте меня начало клинить - получается любая функция как ее ни укажи является статической? Попробую вызвать с созданием экземпляра объекта:
$obj->tellme();
Результат: ОК
А если вызвать сразу двумя способами??
$obj = new test();
$obj->tellme();
Результат: ОКОК
Внимание, вопрос: получается, что все функции всегда являются статическими? Хотя последний пример показывает, что она статическая и не статическая одновременно. Как такое может быть? Или я что-то не так делаю? Может пора спать?
Apache 2.2.17, PHP 5.3.5
но вообще и твой первый и твой второй и твой последний коды должны кинуть E_STRICT, которое обычно отключают))) включи E_ALL | E_STRICT и увидишь)
Сейчас у тебя вырожденный пример. Да, надо больше спать. :)
Такого быть не должно, я досконально изучил документацию вдоль и поперек - там ни слова об этом. Проверять неохота тем более что вне зависимости от результата проблема остается.
не может)) статик - это то, что объявлено как static... если обратиться к не-static переменной через ::, то вообще кинется фатал, а функциям пофигу, они отработают как бы к ним не обращались, а если внутри нету явно отличающихся обращений (так как внутри static-функций нету $this, там только self) то кинется E_STRICT
в чём проблема-то? включить уровень E_STRICT и получать в лоб ошибки))
Да вы правы - выводит уведомление...
Получается сам язык написан так, чтобы на нем говнокодить... Как-то я даже расстроился - оказывается кидатели какашек в РНР не так уж сильно неправы, как я думал раньше.
Проблема в том, что такого быть не должно. Это неверная реализация ООП. Зачем тогда вообще нужно это объявление static если и так все работает прекрасно? Зачем делать вид, что у нас почти полноценное ООП? Эххх...
А ты попробуй обратное: объяви её static и попробуй использовать как метод объекта. Тогда всё понятнее будет )))
Где-то у меня старенькая книга Котерова кажется, писанная ещё во времена PHP 5.0, там очень подробно излагается, что классы используются в виде библиотек функций, без создания каких-либо объектов. И так прямо и написано, зачем существует определение static - аккурат чтобы уточнить функцию класса, которая никогда не будет методом объекта.
Уже настолько привык в Delphi писать кучу методов с одним именем, но разными параметрами, что в PHP без этого счастья как-то обломно.
вы не представляете, какое это на самом деле счастье))) всё аккуратненко, никаких однострочников, которые потом сто лет искать) и скобок, скобок фигурных нет. и ; нет. это конфетка, а не язык)))
Терпеть не могу, когда какие-то чуваки непонятные решили за меня как выглядеть моему коду. Годы проведенные в С/С++ приучили меня к красивому и четкому коду поэтому у меня и без всяких Пайтонов все оформлено. Лично для меня фигурные скобки - каждая на отдельной строке, отступы по 3 пробела - все это намного нагляднее, чем отступы в пайтоне. Возможно привычка - не спорю.
"Странно", думаю. Ну всякое бывает, может не углядел в документации, что по умолчанию методы считаются статическими, если не указано явно. Задаем тогда видимость.
Эээ... По всей видимо только меня смущает тот факт, что в контексте статического метода упоминается видимость?
Областью видимости метода как внутри, так и снаружи управляют через public, private, protected. Принадлежность метода к самому классу или к инстансу объекта определяет наличие static. Наличие static при объявлении класса говорит лишь о том, что метод принадлежит к классу, а не объекту и вызван может быть без создания экземпляра класса (но ни как не управляет видимостью). Особенность тут в том, что внутри кода класса обратиться к методу придется через self, а не через this ибо экземляра то класса у нас может и не быть. А может и быть. Поэтому ни чего проблемного тут нет.
Да, вызывать не статический метод статически конечно же неправильно, но PHP нам об этом вообще то говорит (Static Keyword):
Calling non-static methods statically generates an E_STRICT level warning.
Уже настолько привык в Delphi писать кучу методов с одним именем, но разными параметрами, что в PHP без этого счастья как-то обломно.
А тебе какой overloading? Все вроде есть. Хочешь на уровень объектов, велкам: Overloading (к примеру в твоем случае используя __call). Не устраивают встроенные функции, так и на них управа найдется через APD: override_function (но использовать не рекомендую).
Скорее всего привычка. Ведь когда то какие то чуваки же решили, что вот будут у нас фигурные скобочки ;) Я вот тоже жертва привычки, но по мне все же ни один из подходов не может считать правильным или не правильным. Просто тут принято так, а тут так.
ЗЫ. Покапайся в эрланге, может понравится.
Была мысль, что если не указана видимость, то метод по умолчнанию считается static public. Однако это не подтвердилось. Как бы там ни было РНР реализует корявую неверную модель. Если метод задан как нестатик, то он не должен вызываться через ::. В итоге получается простор для быдлокодинга. Объявление таким образом вообще теряет какой-либо смысл. Ну вывод он там какое-то предупреждение, которое в 99% случаев отключено и не показывается. Хотя для protected и private он реализует верную модель - не дает использовать методы там где их быть не должно. Почему реализация статических методов такая кривая и убогая я лично так и не смог выяснить. Я расстроен((
Пример в Delphi:
private
procedure AnyProc(var AData: string); overload;
procedure AnyProc(var AData: TStrings); overload;
end;
implementation
{TObj}
procedure TObj.AnyProc(var AData: string);
begin
.................
end;
procedure TObj.AnyProc(var AData: TStrings);
begin
.................
end;
end;
А вот в PHP хрен так сделаешь.
private
procedure AnyProc(var AData: string); overload;
procedure AnyProc(var AData: TStrings); overload;
end;
implementation
{TObj}
procedure TObj.AnyProc(var AData: string);
begin
.................
end;
procedure TObj.AnyProc(var AData: TStrings);
begin
.................
end;
end;
А вот в PHP хрен так сделаешь.
если очень нужно - сделаешь.
но я не вижу смысла.
а что мешает обьявить ОДИН метод, который принимает ЛЮБОЙ аргумент, и в зависимости от типа действует по другому? Это ПХП, ему фиолетово что вы передадите, масив, екземпляр класса или число - главное потом правильно обработать
if(!is_array($mixed))
$arr[0]=$mixed;
else
$arr=$mixed;
foreach($arr as $a)
echo $a;
}
еще множественное наследование вспомните :)
Хочешь задавай.
Конечно согласен есть мааленькое ограничение. Задавание типов работает только с массивами и объектами. Но все же.
<?php
function f(array $a) {
print_r($a);
}
$b =2;
f($b);
?>
`--> php test.php
Catchable fatal error: Argument 1 passed to f() must be an array, integer given, called in /home/lonewolf/test.php on line 6 and defined in /home/lonewolf/test.php on line 2
Ты просто думаешь о static как о сущности привязанной к видимости. Но это не так. static это одна сущность, public, private, protected другая. Они ни как между собой не связаны.
static - любая функция в классе. Ну так в PHP заложено. И она будет static ровно до того момента, пока нерадивый человек не станет внутри неё использовать поля и методы объекта, который якобы сконструирован.
А вот в PHP хрен так сделаешь.
Почему? О_о
class TObject
{
public function AnyProc($AData)
{
if (is_string($AData)) {
return $this->_string($AData);
} elseif (is_array($AData)) {
return $this->_array($AData);
}
return false;
}
private function _string($string)
{
return 'STRING';
}
private function _array($array)
{
return 'ARRAY';
}
}
$obj = new TObject();
$str = 'string';
$arr = (array) $str;
var_dump($obj->AnyProc($str)); // string(6) "STRING"
var_dump($obj->AnyProc($arr)); // string(5) "ARRAY"
PHP не строго типизированный язык, поэтому тут все зависит только от тебя. Ты просто в контексте дельфи привык думать в плоскости "хочу в метод передать аргумент типа Х, поэтому делаем перегрузку ранее объявленного метода, но с типом аргумента Y", имхо. Но тут нужно просто взять и написать метод. Код обработки в зависимости от типа аргумента можно написать как в этом методе, так и, к примеру, вынести в приватные методы как с мое примере.
Я замечу, что писать на одном языке в стиле другого - прямая дорога к быдлокодерству. Язык - инструмент, со своими плюсами и минусами, на сколько эффективно этот инструмент используется зависит только от самого программера. Вворачивать шурупы всегда будет эффективнее отверткой, чем молотком.
Вполне возможно: pecl - operator.
Ты видел, чколько написано в Delphi и сколько усилий для overload нужно сделать? Там ровно две процедуры. Ты приводишь пример откровенно через жопу, уж извини. )))) Никогда такой overload не стану делать. Мне проще два метода раздельно написать. Так хоть код понятный будет, а не рыскать по всем условным местам что и кто в каком случае мне сделает ))))
А у нас есть где-то библия ООП в которой сказано, какой путь ведет нас в светлое будущее, а какой в гиену огненную? Нужно просто понимать, что есть какая то идея, концепт, а есть реализация этой идеи. А как наиболее правильно реализовать идею виднее все же реализующим.
Это да, но все же PHP изначально не был объектно-ориентированным языком, он погнался за новыми языками, в которых это уже было реализовано. А коли так - разумнее было бы сделать, чтобы программист, который в 2-3 языках уже привык к некоторой "общепринятой" реализации некоторых концепций, не ломал себе голову, а почему же в PHP она другая. Не согласны?
Ты видел, чколько написано в Delphi и сколько усилий для overload нужно сделать? Там ровно две процедуры. Ты приводишь пример откровенно через жопу, уж извини. )))) Никогда такой overload не стану делать. Мне проще два метода раздельно написать. Так хоть код понятный будет, а не рыскать по всем условным местам что и кто в каком случае мне сделает ))))
Я так и думал, что ты попытаешься сделать упор именно в этом строну. Между тем он не сильно больше примера на дельфи, просто он кажется больше из-за форматирования. По логике там ровно на один метод больше.
А пример да, через жопу, тебе это очевидно и это отлично. Я его и привел как демонстрацию того, что не нужно писать на одном языке категориями другого. В зависимости от типа аргумента требуется два куска кода, ну так и нужно выделять это в два отдельных метода. Не нужно протаскивать идею перезагрузки из дельфи в пхп.
Overload - чертовски удобная штука, замечу. Дело даже не в сочинении имён методам, а как раз в образе жизни. Всё таки ООП - программирование, максимально приближённое к человеческой логике. И вариации на тему входящих подробностей, от которых плясать наиболее нам, человекам, близки.
Алексей - неужели вы думаете что по прошествии стольких лет я до сих пор не понимаю что такое статик и паблик? Еще раз: я думал что если не указывается ни статик, ни область доступности метода, то методу присваивается по дефолту статик паблик. Я решил провести эксперимент - не перестанет ли метод быть статиком, если ему задать область доступности явным образом? Вот и все, не более того.
Весь смысл топика в том, что внезапно выяснилось, что в РНР есть только статик методы и нестатиком их можно сделать только если внутрь метода запихать $this. Тогда метод обвалится с ошибкой. В других случаях как ни выкручивайся метод будет статиком. Хоть там и выводится какая-то ошибка, но она всегда отключена и имеет уведомительный характер.
static - любая функция в классе. Ну так в PHP заложено. И она будет static ровно до того момента, пока нерадивый человек не станет внутри неё использовать поля и методы объекта, который якобы сконструирован.
это с как?
Да если октлючена генерация E_STRICT, динамический метод можна вызвать статически и он выполнится. Причем всегда. но до той точки где обращаешся к $this и сказать что это статический метод - нельзя.
Это тоже самое что называть табуретку стулом, до тех пор пока ты непытаешся облакатится на спинку.
В идеальном мире перфекционистов стоило бы согласиться, но я инженер работающий с реальными системами и посему не согласен.
Любая система которая существует какое то время и развивается содержит в себе атавизмы, возрастающую энтропию кода, костыли эволюции которые возникли потому что первоначальная архитектура не была рассчитана на будущие изменения и кучу другого исторического наследия. При поддержании жизненного цикла продукта приходится думать и об этом. Если авторы решили, что им удобнее реализовать так или иначе это их решение. Кому оно кажется неправильным, неправославным берут и используют другой инструмент или вовсе пытаются создать свой.
Можно конечно выбросить весь предыдущий код и написать все с нуля, по православному, но как оплатить такую разработку и кому в итоге она понадобиться?
А общепринятой реализации нет как и нет серебряной пули. Есть идея которая, замечу, так же эволюционировала и есть различные реализации этой идеи.
Именно так. Если $this нет в коде, то метод фактически является статиком (ну что с того что он каком-то там особом режиме создает нотайс).