Тайпхинтинг: интерфейс или типы объектов

zerkms

TDD infected
Команда форума
Тайпхинтинг: интерфейс или типы объектов

[Внимание: очень холиварный пост]

PHP:
<?php   

class a
{
    function foo()
    {
        return 'a::foo()';
    }
}

class b extends a
{
    function foo($arg)
    {
        return 'b::foo()';
    }
}

function c(a $obj)
{
    echo $obj->foo();
}

c(new a());
c(new b());
внимание вопрос: если тайпхинтинг лишь проверяет тип объекта (точнее - нахождение объекта в иерархии наследования ниже искомого), но не регламентирует протокол общения (интерфейс) - какой смысл в нём?

ps: об интерфейсах я знаю, мне интересно поведение именно приведённого выше кода.
 

Sokil.Dmytro

Новичок
я вроде как большой :) теоретик ооп но твой код нарушает принцип полиморфизма - один интерфейс - разная реализация
 

zerkms

TDD infected
Команда форума
Sokil.Dmytro
угу. нарушает парадигму, но соответствует синтаксису. я уже сказал - что я знаю и умею интерфейсы.
тезис поста в том, что если тайпхинтинг, применённый к интерфейсу, свою работу выполнит - гарантирует работоспособность функции, то тайпхинтинг с именем класса совершенно бессмысленен.
 

Sokil.Dmytro

Новичок
я тебя сейчас через слово понимаю :) насколько я єто кашу понимаю, то тайпхинтинг указывает на то, что агрумент следует интерфейсу указанного класса. и если туда передать б который уже не следует интерфейсу а, будет ругань. так?
по моему он как раз и указывает, какой интерейс ожидается

а ты пытаешь б использовать как а, привязывая тип к аргументу. правильно вроде понял? :)
 

zerkms

TDD infected
Команда форума
Sokil.Dmytro
конечно будет ругань.
а непонятки (у меня) из-за того, что тайпхинтить можно как интерфейсы и абстрактные классы (правильно), так и обычные классы. в случае последних - проверяется лишь вхождение в иерархию наследования. по факту - наследник может передекларировать метод как ему угодно, что поломает функцию с тайпхинтом.

какое поведение я бы ожидал от пхп: на этапе трансляции он выкидывает фатал или варнинг с указанием, что тайпхинтить можно интерфейсы или абстрактные классы.
всё: теперь работоспособность функции будет гарантирована самим ЯП.
 

Sokil.Dmytro

Новичок
так оно вроде и говорит
Strict Standards: Declaration of b::foo() should be compatible with that of a::foo()
не фатал правда но все же :)
 

zerkms

TDD infected
Команда форума
php 5.2.8 не говорит такого с error_reporting (E_ALL | E_STRICT);
но с указанным стриктом в пхп.ини говорит :)

согласен - решение...
 

x-yuri

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

zerkms

TDD infected
Команда форума
x-yuri
чушь. до того, как Sokil.Dmytro напомнил о стрикте - я вполне привёл "решение" для пхп, которое не ломало бы идеологии языка с слабой типизацией.

Кроме того, можно использовать вещи не по назначению (или просто не разумно).
ЯП может и должен ограничивать это.
 

Sokil.Dmytro

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

x-yuri

Новичок
человек, использующий статические языки, тоже может возмущаться, почему у него нет возможности в php указать жестко тип переменной
да, не совсем удачная аналогия

но с
ЯП может и должен ограничивать это.
я не согласен. Что-то можно ограничить, что-то нельзя. Появились же почему-то динамические языки. Т.е. почему-то программисты решили убрать часть вроде бы полезных ограничений
 

zerkms

TDD infected
Команда форума
x-yuri
Т.е. почему-то программисты решили убрать часть вроде бы полезных ограничений
их не убирали - их просто не добавили. основной тезис стартового поста: тайпхинтинг по классу не гарантирует ничего -> бессмысленен.
 

x-yuri

Новичок
Кроме того, можно использовать вещи не по назначению (или просто не разумно).
я имел в виду, что всегда будут люди, которые будут использовать вещи не по назначению. Иногда это будет оправданно, но в большинстве случаев - нет

-~{}~ 13.01.09 01:55:

основной тезис стартового поста: тайпхинтинг по классу не гарантирует ничего -> бессмысленен.
хорошо, давай на этом и остановимся
 

korchasa

LIMB infected
Автор оригинала: zerkms
...основной тезис стартового поста: тайпхинтинг по классу не гарантирует ничего -> бессмысленен.
Не так: "тайпхинтинг по классу не гарантирует ничего, ибо наследник может изменить интерфейс".

ИМХО, нелогична именно смена интерфейса наследником. Сейчас насколько я помню есть два варанта поведения:
- методы, производные от абстрактных методов и методов интерфейсов, должны четко следовать интерфейсу
- методы, производные от методов обычных классов, и методов реализованных в абстрактном классе, могут его менять
 

zerkms

TDD infected
Команда форума
korchasa
угу, и 2 поведение сопровождается выбрасыванием варнинга уровня E_STRICT. что хоть как-то ситуацию исправляет.
 

crocodile2u

http://vbolshov.org.ru
Все правильно. PHP сообщает об ошибке прогаммиста, но (и это в духе PHP) разрешает ему писать так, как ему хочется (при условии подавления E_STRICT на этапе компиляции: вызов error_reporting() непосредственно в скрипте не влияет на это поведение, что вполне логично)
 

zerkms

TDD infected
Команда форума
crocodile2u
угу, логично, сразу не подумал, что включать рантаймно, когда уже всё оттранслировалось - поздно.
но странно, что в документации это не указано. или я снова проглядел?
 

Sokil.Dmytro

Новичок
korchasa

если вы меняеете интерфейс - вы не пользуетесь ооп, вы пользуетесь щедростью языка программирования
 

korchasa

LIMB infected
crocodile2u
Оп-па. Спасибо. Не знал, про то, что это работает на компиляции.

О сколько нам граблей прекрасных
Готовят тайны в РНР.

Sokil.Dmytro
Спасибо, я в курсе.
 
Сверху