На сколько я знаю, PHP не поддерживает ни доопределения функций, ни операторов, так как нормально не можно проверять входящие аргументы на этапе поиска функции по сигнатуре (которого нет). Как эти моменты можно тонко обойти? P.S. Цель - добиться программирования в безопасном строго типизированном режиме.
Но PHP: <?php function test (int $a, bool $b) {} function test (int $a, bool $b, bool $c) {} ?> не пройдет по двум причинам - мы не можем отслеживать типы аргументов примитивных типов, мы не можем доопределять функции по сигнатуре.
PHP: <?php class Someclass { public function somef($intVar){ if(!is_int($intVar)){ // throw new Exception; } } } $ab = new Someclass(); $ab->somef('abc'); ?> Проверку можно организовать грамотно, если это нужно. Насчет последнего я не понял.
Простой пример, мы хотим определить 4 конструктора для класса триугольников - 1) по всем координатам каждой точки, 2) по трем точкам-объектам, 3) по трем отрезкам-объектам, 4) и конструктор копирования другого триугольника; выглядит это приблизительно так: PHP: <?php class Triangle { //... public function __construct (int $x1, int $y1, int $x2, int $y2, int $x3, int $y3) { //... } public function __construct (Point $p1, Point $p2, Point $p3) { //... } public function __construct (Vector $p1, Vector $p2, Vector $p3) { //... } public function __construct (Triangle $t) { //... } } ?> То есть, в зависимости от входящих аргументов, вызывается тот или иной конструктор. По поводу проверки входных аргументов, твой способ нельзя назвать слишком элегантным...
T-Mon, если не ошибаюсь, в РНР нельзя перегружать методы, есть только возможность переопределять их в дочерних классах. Я не претендую на элегантность, я говорю о том, что не так уж это и невозможно, и в качестве примера набросал код. Само собой РНР != С++ и одно из его преимуществ (так считается) - это компромисс по отношению контроля типов. Я, когда начал писать на РНР, постоянно перед переменной писал int $var
Это возможно, и я чудесно понимаю, что аргументы можно проверять просто внутри метода, а вместо доопределения методов можно по аргументам внутри определять, что делать. Но это все громоздко, неудобно и склонно к ошибкам. Кстати, на счет С++, я его тоже не очень люблю (а программировать на нем вообще не умею) из-за его ужасных явных указателей и определений классов за пределами классов. А за что я уважаю С++, это доопределение операторов, чего просто ужасно не хватает в PHP и Jav'е. P.S. "Перегрузка" не совсем корректное слово в плане перевода, а уж тем более в плане смыслового значения. Если переводить "overloading" с английского, то это скорее будет "догрузка", "надгрузка", а точнее "доопределение" - то есть добавление дополнительного смысла. "Перегрузка" уже больше по смыслу сходно с "Overriding" - переопределению методов класса.
Ну корректное оно или некорректное, исторически сложилось так, что во всех пособиях по изучению языков overloading всегда переводилось как "перегрузка" операторов. Если же вдаваться в семантику английского языка, то тут неправы вы. Overloading никак не переводится "надгрузка" или "догрузка", приведу даже пример, дабы не быть голословным: overate - переесть, look over - пересматривать, если копать дальше, в недры суфикса over-, то можно констатировать факт, что over- переводится на русский над-, пере-, сверх-. Простите, я английский не в школе учил, одно из требований там, где я работаю - fluent English. Посему, для меня незнание таких элементарных вещей было бы равносильно увольнению. На этом закончим разбор грамматических структур. Что касается перегрузки (да-да, именно так правильно), то нефиксированное количество аргументов, их логическая проверка по типам, классификация - это не имеет ИМХО смысла делать на РНР, по крайней мере сейчас. Кстати: Встроенными средствами это сделать невозможно, как бы вы что прекрасно там не понимали. Собственно это те причины, по которым я люблю С++ и езжу на нем уже пол своей жизни.
1) По поводу "overloading", один преподаватель мне подробно объяснил, что то единое слово "overload", которое буквально переводится, как "перегружать", "отягощать" (Lingvo), нужно рассматривать первоначально как два отдельных слова "over" - "над", "сверху", "дополнительно" (совсем не в негативном значении) и "load" - "нагружать" (в нашем контексте "смысловая нагрузка", "функциональная нагрузка"). Что означает, что наши функции имеют дополнительную (альтернативную) функциональную нагрузку, то есть их функциональность была доопределена. Английский язык - язык краткий, и берясь за перевод нельзя вырывать фразы из контекста и просто переводить, как есть. А контекст нам подсказывает, что мы эти функции не "чрезмерно загружаем" и не "переотягощаем", а "доопределяем". Если исторически сложилось, что каждый второй программист называет вещь словом, которое абсолютно не соответствует ее смыслу, это по крайней мере должно заставлять задуматься - стоит ли мне повторять ту же глупость за другими, или же называть вещи своими именами. Так сложилось, что я тоже неплохо учил английский, может не так хорошо, как ты, но имел опыт перевода текстов, и знаю, что зачастую значения слов подбираются не только прямым сопоставлением со словарем, но и согласованием с контекстом. 2) По поводу доопределения методов (да-да, именно так корректно), оно позволяет строить элегантные приложения с минимальных риском допускания ошибки и максимальным удобством для программиста, дальнейших модификаций и редактирования. 3) Как ни странно, возможно, но грубо и небезопасно: PHP: <?php function test () { $args = func_get_args (); $num = func_num_args (); switch ($num): case (1): if (is_int ($args [0])): //Code... echo ('Call function with 1 arg: ' . $args [0] . '<br />'); else: throw new Exception; endif; break; case (2): if (is_int ($args [0]) && is_int ($args[1])): //Code... echo ('Call function with 2 int args: ' . $args [0] . ' and ' . $args [1] . '<br />'); elseif (is_int ($args [0]) && is_bool ($args[1])): //Code... echo ('Call function with 1 int arg and boolean: ' . $args [0] . '<br />'); else: throw new Exception; endif; break; default: throw new Exception; break; endswitch; } test (1); test (2, 3); test (3, true); try { test (); } catch (Exception $exc) { echo ($exc); } ?> 4) По поводу указателей еще готов понять - они обеспечивают контроль программиста над приложением (особенно smart pointer'ы), хотя и могут зачастую привести к неожиданным утечкам и крахам. Но вот по поводу определения классов в заголовных файлах, а их функционала за их пределами - не вижу ни каких приимуществ.
1. И всё-таки насчет перевода я крайне несогласен. Ваш преподаватель основывается на синтаксическом разборе слов, но проблема в том, что прибавление суффиксов или аффиксов часто ведет к образованию совершенно новых слов. Возмем старое русское слово "единый", от которого произошло современное слово "один". В настоящее время это два абсолютно разных по значению слова, ранее слово "единый" было точь в точь равно нашему слову "один". Я учился в основном по английской литературе, если брать С++, то тут на 100% на английском, С# читал на русском. И эта терминология уже считается официальной не смотря на то, как оно переводится. Всё адаптируется под смысл, лексику и так далее. 2. Ваше доопределение непонятно. Пускай вы считаете, что так правильно, но пользуйтесь общепринятой терминологией во избежании недопоминания. 3. Вообще, проверку типов я делаю только там, где это необходимо и действительно есть риск. Для int всегда вызываю функцию intval(), любую строку представляет как надо ('asdka' -> (int) 0), для float - floatval(). Самая распространенная ошибка или предумышленная подстановка - замена числового параметра строкой. Касательно bool значений, то можно представить truе/false как 1/0 - любая строка будет 1, отсутствие - 0, или же приводить данные к числовому типу, в случае строки - 0, иначе любое числовое значение - 1 4. В принципе, речь шла об указателях. Насчет объявлений классов - так это сугубо дело стиля, в целях дебага больших проектов все средства хороши.
1) Я спорить больше не буду, просто буду употреблять слово "доопределение" в надежде, что меня поймут. Просто слово "перегрузка" лишено всякой связи с тем, что оно обозначает. 2) Не могу, в виду того, что слово "перегрузка" в данном значении меня ужасно раздражает, на подсознательном уровне, а особенно в литературе. 3) А тут я уже не особо что-то понял, пример, если можно... 4) Явные указатели очень опасны, особенно в крупных приложениях. К сожалению, JAVA уже отпала, так как работать с ней в Internet не удобно. Осталось только узнать, как там с С#. Если и С# меня не удовлетворит - буду писать компилятор из PHP++ (модифицированный мною PHP) в PHP.
3. PHP: <?php class Someclass { public function check($intVar, $floatVar, $str, $boolVar) { $intVar = intval($intVar); // Работаем со значением как (int) $floatVar = floatval($floatVar); // Работаем со значением как (float) $str = strval($str); // ЯВНО преобразуем значение в строку settype($boolVar, "boolean"); // Приведение значения к типу bool // Вывод получившихся переменных echo '<pre>'; var_dump($intVar, $floatVar, $str, $boolVar); } } $cls = new Someclass; $cls->check(10, 20.56, 'Hello, World', true); // Передача корректных аргументов $cls->check('abc', 'def', false, 645); // Передача НЕКОРРЕКТНЫХ аргументов $cls->check(-5454.78, true, 0, 'Somethis'); // Передача НЕКОРРЕКТНЫХ аргументов ?>
Слово "интернет" тоже раздражает? Пользуй питон. За исключением момента с duck typing, это язык строгой типизации. И достотачно удобный в Internet. Упомянутый "утиная типизация" просто определяет тип переменной во время указания: Код (Text): someint = 5 sonestring = 'test' try: someint + sonestring except TypeError: print 'Операция с несовместимыми типами.' Пхпшные игрища с типами так прекрасны. Не понимаю, почему люди начинавшие с других языков не любят столь мягкие и податливы типы в php. Просто чтобы не получить непредсказуемый результат следует либо приводить к желаемому типу входящие данные, либо исходящие: PHP: <? function test($array1, $array2){ return array_merge((array)$array1, (array)$array2); } test('hop', array('lya'));