как грамотно спроектировать вызов статичных методов наследуемого класса

jonjonson

Охренеть
Sanchez, вообще то в php4 синглетон реализуем. А как связано отсутствие типизации данных с возможностью реализации синглетона?
 

Sanchez

Новичок
Я сказал навскидку - вполне возможно и реализуем. А про типизацию я говорил с точки зрения того, что getinstance должен вернуть ссылку на самого себя, а после этого должна быть возможность обратиться к методам и атрибутам класса - не знаю, пропустит ли интерпретатор такое - ему ведь неизвестно, что там вернул метод (т.е. объект ли это, или может простое число - какие там тогда методы).
 

jonjonson

Охренеть
Sanchez, не нужно говорить на вскидку и не зная. Особенно бред. А следуя вашей логике даже оператор + не должен работать, так как не известно являются ли переменные числами. И что тогда делать бедному интерпретатору?
 

alexei.lexx

Новичок
Вот пример кода, иллюстрирующий проблему.

PHP:
class A {
	public static function func() {
		echo 'A';
	}
	
	public static function callFunc() {
		self::func();
	}
}

class B extends A {	
	public static function func() {
		echo 'B';
	}
}

B::callFunc();
Этот коды выведет "A" вместо желаемого "B".

-~{}~ 03.05.07 10:42:

Вот выдержка из документации PHP5.

In fact static method calls are resolved at compile time. When using an explicit class name the method is already identified completely and no inheritance rules apply. If the call is done by self then self is translated to the current class, that is the class the code belongs to. Here also no inheritance rules apply.
 

leadaxe

Новичок
Во первых вы подняли очень интересную проблему. Это связанно с тем что метод принадлежит не объекту класса а объекту класса класс. Т.о. переопределить его нельзя,т.к. нет механизмов супер классов.

Я думал что можно попробовать создать "костыль". Правда тяжелый.
Вопрос теоретический, поэтому код я писать не буду, только рекомендации.
в классе А func() определи следующее поведение:
1 возьмем все классы(get_declared_classes())
2 выделим те что унаследованы от А
3 Тут надо придумать как узнать в контексте кого вызван

Но пришел к выводу что это не нужно и не возможно. Вот пример, показывающий невозможность:
PHP:
<?php

class A {
    public static function func() {
        echo 'A';
        print_r(debug_backtrace());
    }
    
    public static function callFunc() {
        self::func();
    }
}

class B extends A {    
    public static function func() {
        echo 'B';
    }
}

B::callFunc();
?>
Выводит:
AArray
(
[0] => Array
(
[file] => PHPDocument1
[line] => 10
[function] => func
[class] => A
[type] => ::
[args] => Array
(
)

)

[1] => Array
(
[file] => PHPDocument1
[line] => 20
[function] => callFunc
[class] => A
[type] => ::
[args] => Array
(
)

)

[2] => Array
(
[file] => C:\Program Files\Zend\ZendStudioClient-5.0.0\bin\php5\dummy.php
[line] => 1
[args] => Array
(
[0] => PHPDocument1
)

[function] => include
)

)

Как видите раннее связывание вовсе не оставляет информации.

смотрите
[1] => Array
(
[file] => PHPDocument1
[line] => 20
[function] => callFunc
[class] => A
[type] => ::
[args] => Array
(
)

)

Принципиально костыль выглядит так: Вы сами читаете строку, смотрите что за имя класса и внутри func класса А
пишите
1. если это другой класс, то (2) иначе вывод и конец
2. Есть ли в этом другом классе func.
3 если нет то вывод и конец иначе вызов func другого класса (имя вы можете прочесть только из файла программы!, а где читать найти по дереву отладочной инфы)

Т.о. Если б мне это кровь из носа нужно было б, то я сделал, но не советую вам.
Объясню почему.
Дело в том что лучше замените запись

B::callFunc();
на запись
A::callFunc('B);

Т.е. явно передайте инф. об объекте это эффективнее, и вы все равно его указываете в B::, так что вы ничего не усложняете и не теряете.

На сем для себя тему я закрыл. Но если кто-то предложит нечно более "правильное" с удовольствием посмотрю.
 

T. Anre

Новичок
Вывод:
Статичные классы должны быть финализированными?
 

cursedj

Новичок
Автор оригинала: leadaxe
Во первых вы подняли очень интересную проблему. Это связанно с тем что метод принадлежит не объекту класса а объекту класса класс. Т.о. переопределить его нельзя,т.к. нет механизмов супер классов.
Да в PHP нет понятия метакласов. Да и зачем языку, у которого и нормальной поддержки ООП, если присмотреться, то нет, еще и метаклассы.
А статические методы судя по официальной документации и их поведению в PHP 5 реализованны как обычные функции, только содержащиеся в пространстве класса (получаеться какое-то подобие одноуровневых пространств имен). Аналогичная ситуация и со статическими переменными класса.

Кстати о пространствах имен, очень полезная вещь которой не хватает в PHP, и наверное разработчики не намеренны их реализовывать в будущих версиях. Да и вообще если добавлять ООП в язык, то хотя бы реализовать его в полном объеме, иначе это будет только мешать при программировании.

Вот пример, добавили возможность перегрузки доступа к переменным объекта (через __set() и __get()),
а перегрузки стандартных операций для объектов не сделали (например через методы __add(), __sub() -- операции + и -), хотя это было бы очень уместно.
 

dark-demon

d(^-^)b
мда.. на какие только ухищрения не идут лишь бы не создавать объект...
 

Sanchez

Новичок
Да, согласен, поработал в пхп5 - все равно хилая поддержка ООП... Многое отстутствует из-за отсутствия типизации - например, перегрузка - очень жаль..
Кстати, приведение объекта к родительскому классу возможно?

Вообще, честно говоря подумываю уйти в asp.net , т.к. преимущества си-шарпа подкупают)))
 

Crazy

Developer
Автор оригинала: Sanchez
Да, согласен, поработал в пхп5 - все равно хилая поддержка ООП... Многое отстутствует из-за отсутствия типизации - например, перегрузка - очень жаль..
Ох бедные программисты, пишущие на Smallltalk. Какой у них, оказывается, бедный, никчемный язык...
 

Sanchez

Новичок
Crazy
Ну а чем ты ответишь на отсутствие перегрузки в пхп? Да и что-то народ больше пишет на С++, чем на смалталке, который я вообще встречал больше как пример для сравнения с С++ )))
 

Crazy

Developer
Я отвечу, что:

1. Перегрузка вредна. Практически не существует случаев, когда от нее больше пользы, чем вреда.
2. Доля людей, профессионально пишущих на C++, в программистском сообществе слищкомнизка, чтобы кто-то всерьез ориентировался на привычки человека, после 10 лет программирования на C++ решившего перейти на PHP.
3. Перегрузка вообще не имеет никакого отношения к ООП.
 

Crazy

Developer
Тем, что при чтении кода может складываться неверное представление о том, какой именно код здесь будет выполнен.
 

cursedj

Новичок
Автор оригинала: Crazy
Тем, что при чтении кода может складываться неверное представление о том, какой именно код здесь будет выполнен.
Что-то я смотрю у тебя, наверное после PHP, сложилось неверное представление об ООП. Перегрузка, или более точный перевод - совмещение (overloading) - это один из основных механизмов полиморфизма и повторного использования кода. Суть перегрузки в том, что она позволяет создавать различные реализации одной и той же спецификации. То есть, смысловую нагрузку несет имя метода, а какой код будет выполнен -- решать механизму совмещения. При этом, если, например, совмещенный метод называеться Add в классе реализующем список произвольных объектов, то какой бы вариант кода не вызывалься, понятно, что он будет выполнять добавление объекта к списку, согласно его спецификации. Теперь вы можете в том же класе, или в любом производном сколько угодно добавлять совмещенных методов Add, каждый из которых выполняет свой собственный код, в соответствии со своей спецификой, например метод , но реализующий общую спецификацию Add(int pos, string item) добавляет строку как элемент списка в указанную позицию, а метод Add(string item) добавляет строку в конец списка. Но при этом все они реализую общую спецификацию -- добавление элемента в список.

На PHP такое не реализуеш:
PHP:
class StringList : public List
{
    virtual int Add(String *item);
    virtual int Add(int pos, String *item);
    virtual int Add(int pos, int count, String *items[]);
    virtual int Add(int count, String *items[]);
}

StringList *list = new StringList();
list->Add("Ну");
list->Add("непонятного?");
list->Add(1, 2, new String[] {"что", "тут"});
list->Add(2, new String[] {"это", "C++"});
Хотя нет, вру, реализовать можно, но как:
PHP:
class StringList extends List
{
    function Add($item, $pos = -1) {
       // Если pos == -1, то добавляем в конец списка
       // иначе, добавлем в указанную позицию
       // о и еще одно, не забыть проверить, что $item -- строка, а $pos -- число.
    }
    function AddRange($items, $pos = -1) {
       // Аналогично, необходимы проверки типов, и аргументов.
    }
}

$list = new StringList;
$list->Add("Вот");
$list->AddRange(array('на', 'PHP'));
$list->AddRange(array("это","делаеться"), 1);
$list->Add("так", 1);
Вот такая простая ситуация, а если число сигнатур метода Add() увеличиться, то в PHP придеться создавать методы с различными именами, и вся иллюзия присутствия, хотя бы возможности реализации, совмещения и полиморфизма в PHP исчезает.

-~{}~ 14.06.07 10:04:

Автор оригинала: Crazy
Я отвечу, что:

1. Перегрузка вредна. Практически не существует случаев, когда от нее больше пользы, чем вреда.
2. Доля людей, профессионально пишущих на C++, в программистском сообществе слищкомнизка, чтобы кто-то всерьез ориентировался на привычки человека, после 10 лет программирования на C++ решившего перейти на PHP.
3. Перегрузка вообще не имеет никакого отношения к ООП.
Пункт 3 - см. мой предыдущий пост, или лучше возми наконец, любую книжку про ООП и прочитай.:)
Пункт 2 - Доля людей, профессионально пишущих программы вообще и на C++, в частности конечно же намного меньше разных быдлокодеров и недопрограммеров, считающих себя хакерами, написав очередной "заменитель Notepad'а" или скрипт доски объявлений, который падает каждый третий релоад сыплет варнингами и фаталами как из рога изобилия.
Кроме того, это как ж с какого перепугу проф. программер C++ решить перейти на PHP?:confused:
Пункт 1 - скажи это Гради Бучу:p
 

Sanchez

Новичок
Ну вот за меня ответили и более грамотно :)
Честно, я не ставил цели "зачморить" пхп, он мне много денег принес и еще наверняка принесет, просто по другой работе писал большой проект на си-шарпе (а это полностью объектный язык), просто скажу, что разница есть и заметная.. Больше удивляет не то, что этого не было в 4-м пхп, а то, почему не ввели в 5-м? Почему например нет нормальных перечислений? Почему нет что-нибудь типа "пространства имен"? Приходится мучиться с этими inc-файлами, и потом вспоминать где что забыл подключить, я уж молчу что нет таких мощных средств разработки, типа VS 2005. Для последней есть плагин, но работает он довольно криво..
При всей моей любви к пхп, я щас смотрю в другую сторону... А очень не хотелось бы, если бы в нем устранили эти недостатки я бы с большой радостью остался с ним :)
 

cursedj

Новичок
Вот и я о том же! PHP сейчас СИЛЬНО отстает по функциональным возможностям, не то что от таких "монстров" как .NET Framework, а даже от своих ближайших конкуренов Perl 5.8 и (скоро уже) Perl 6, Python, и Ruby. При этом солидные люди говорят об использовании PHP в качестве платформы разработки web-приложений промышленного уровня (не будем показывать пальцами -- Zend.com)? :)
 

phprus

Moderator
Команда форума
cursedj
PHP сейчас СИЛЬНО отстает по функциональным возможностям
В чем именно он отстает и самое главное от кого?

от своих ближайших конкуренов Perl 5.8
Можно подробнее описать это отставание?

(скоро уже) Perl 6
Это скоро уже длиться 7 лет. Так что не известно сколько это еще продлиться.
 

cursedj

Новичок
От кого я уже писал, а чем? о об этом можно написать ТОЛСТУЮ книгу, и пришибить ею разработчиков PHP (всех сразу):).
Поэтому упомяну только наиболее значительные:
Во первых -- перегрузка методов.
Во вторых -- динамическая типизация.
В-третьих -- пространства имен и модули.
В-четвёртых -- Unicode.
В-пятых -- НОРМАЛЬНАЯ поддержка ООП. (финальные методы есть, финальные классы есть, а финальных переменных объекта - нет;
перегрузка (совмещение) методов, список можно продолжать...)

Насколько мне известно, в Perl 5.8 есть поддержка Unicode.
 

Crazy

Developer
cursedj, это все разговоры в пользу бедных. Мне было, впрочем, забавно читать твои попытки просветить меня об основах ООП. Улыбнуло.

Но повторяться мне влом. Свою точку зрения я не так давно уже описал.

P.S. Можешь мне поверить, умных слов я знаю больше. :) Так что пугать меня ими не стоит.
 
Сверху