LSP? Не, не слышал.Как вам parent?Код:namespace Bar; interface Foo {} interface FooManager { public function bind():Foo; } class FooImpl implements Foo {} class FooManagerImpl implements FooManager { public function bind():FooImpl { return new FooImpl(); } } //Fatal error: Declaration of Bar\FooManagerImpl::bind() must be compatible with Bar\FooManager::bind(): Bar\Foo in *** on line 14
http://habrahabr.ru/post/258139/#comment_8423963
LSP? Не, не слышал.
public function bind():Foo/*Impl*/ {
return new FooImpl();
}
interface Foo {
public int getId();
}
interface FooManager {
public Foo bind();
}
class FooImpl implements Foo {
public int getId() {
return 1;
}
public int getBar() {
return 2;
}
}
class FooManagerImpl implements FooManager {
public FooImpl bind() {
return new FooImpl();
}
}
class Test {
public static void main(String[] args) {
FooManager fm = new FooManagerImpl();
Foo foo = fm.bind();
System.out.println(foo.getId());
// System.out.println(foo.getBar()); - тут будет cannot find symbol,
// а если двумя строчками выше объявить FooImpl foo - будет incompatible types
FooManagerImpl fm2 = new FooManagerImpl();
FooImpl foo2 = fm2.bind();
System.out.println(foo2.getId());
System.out.println(foo2.getBar()); // а так сработает
}
}
interface Foo {
public int getId();
}
interface FooManager {
public Foo bind();
}
class FooImpl implements Foo {
public int getId() {
return 1;
}
public int getBar() {
return 10;
}
}
class FooImpl2 implements Foo {
public int getId() {
return 2;
}
public int getBaz() {
return 20;
}
}
class FooManagerImpl implements FooManager {
public FooImpl bind() {
return new FooImpl();
}
}
class FooManagerImpl2 implements FooManager {
public FooImpl2 bind() {
return new FooImpl2();
}
}
class Test {
private static void test(FooManager fm) {
Foo foo = fm.bind();
System.out.println(foo.getId());
}
public static void main(String[] args) {
FooManagerImpl fm = new FooManagerImpl();
FooImpl foo = fm.bind();
System.out.println(foo.getBar());
FooManagerImpl2 fm2 = new FooManagerImpl2();
FooImpl2 foo2 = fm2.bind();
System.out.println(foo2.getBaz());
test(fm);
test(fm2);
}
}
<?php
interface A {
public function b();
}
class X implements A{
public function b(){
echo "hallo";
}
public function c(){
echo "world";
}
}
class Test{
private $a;
public function setA( A $a ){
$this->a = $a; // это все одно class X
}
public function fetch(){
echo $this->a->b();
echo " ";
echo $this->a->c();
}
}
$test = new Test;
$test->setA( new X );
$test->fetch();
Вот тут полностью согласен.Ай, типичные хабромудаки, вместо контраргументов придрались к опечатке. Я согласен с Casus, php теряет своё преимущество на простых задачах, а новый функционал строится на костылях
Говнокод в любом случае. Я бы сказал, что тут ещё нарушается DIP. Если где-то нужно напрямую юзать именно FooManagerImpl и FooManagerImpl2, то здесь что-то не так. А по поводу LSP оно может быть неявно: если требуется указывать конкретную реализацию, то не означает ли это, что эта реализация чем-то отличается от контракта? Например, неявный контракт в виде описания исходного интерфейса: «этот метод возвращает положительные числа», а конкретная реализация возвращает и отрицательные.LSP так не нарушается.
Придумать не говнокод у меня не получается, да.Говнокод в любом случае
Кагбэ-строгая типизация при отсутствии объявления типов переменных - вообще штука странная получается. В такой постановке, наверное, по другому и никак.Ну и как бэ PHP
Если полагаться на рефлексию, то зачем вообще полагаться на возвращаемый тип? Вопрос риторический. Не нужно указывать возвращаемый тип, следует полагаться на динамическую проверку, которая установит соответствие реально возвращаемого типа ожидаемому или провалится с каким-нибудь страшным исключением.( (X)$this->a )->c(); тоже нельзя?
Можно считать, что переменной присваивается тот тип, который имеет выражение в правой части.строгая типизация при отсутствии объявления типов переменных