Skip to content

Instantly share code, notes, and snippets.

@andriesss
Created September 17, 2013 07:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andriesss/6590912 to your computer and use it in GitHub Desktop.
Save andriesss/6590912 to your computer and use it in GitHub Desktop.
<?php
interface Comparable {
function compare(self $compare);
}
class Foo implements Comparable {
function compare(self $compare) {}
}
class Bar implements Comparable {
function compare(self $compare) {}
}
$foo = new Foo();
$bar = new Bar();
$foo->compare($foo);
$bar->compare($bar);
@andriesss
Copy link
Author

This works up to PHP version 5.3.19, but it seems that it no longer works for PHP 5.4.X. I have found this: https://bugs.php.net/bug.php?id=60573, but i'm not sure what the outcome of it is.

@patrickvdvelden
Copy link

PHP Fatal error: Declaration of Foo::compare() must be compatible with Comparable::compare(Comparable $compare) in /Users/patrick/test.php on line 7

When I replace 'self' in line 7 and 11 with 'Comparable' it works again. It seems that the 'self' in the interface is resolved to Comparable and the class method signatures are being literally compared to that.
This does sound like a bug to me.

I can only say: avoid using 'self' in signatures in the first place... :)

@andriesss
Copy link
Author

Well, changing the type hint to "Comparable" is not what I need. I'd like to define in the interface, that a method of an implementing class can only accept an instance of itself (the implementing class). This seems no longer possible as of PHP 5.4.1... :(

@Ocramius
Copy link

@andriess I think the interface works fine:

http://3v4l.org/VJTnU

<?php

interface Comparable {
function compare(self $compare);
}

class Foo implements Comparable {
function compare(Comparable $compare) {}
}

class Bar implements Comparable {
function compare(Comparable $compare) {}
}

$foo = new Foo();
$bar = new Bar();

$foo->compare($foo);
$bar->compare($bar);

@andriesss
Copy link
Author

@Ocramius, now the method accepts any class that implements the comparible interface. I want to define that a method can only accept an instance of itself.

@Ocramius
Copy link

@andriesss that could work with the static keyword (unsupported), but is still wrong.

@andriesss
Copy link
Author

Pretty lame, seems like a nice feature, I guess.

@Ocramius
Copy link

@andriesss the fact is that every implementation basically accepts different types of objects. That's a mess from a LSP pov

@andriesss
Copy link
Author

@Ocramius, the only option I have is:

<?php

interface Comparable {
function compare(Comparable $compare);
}

class Foo implements Comparable {
    function compare(Comparable $compare) {
        if (!$compare instanceof self) { 
            throw new \InvalidArgumentException('sometimes php sucks a little');
        }
    }
}

class Bar implements Comparable {
    function compare(Comparable $compare) {
        if (!$compare instanceof self) { 
            throw new \InvalidArgumentException('sometimes php sucks a little');
        }
    }
}

$foo = new Foo();
$bar = new Bar();

$foo->compare($foo);
$bar->compare($bar);

@Ocramius
Copy link

@andriesss that's about right... Again, I don't think that's a PHP issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment