ducktyping is a simple reflection-based duck typing implementation for PHP
If it walks like a duck and it quacks like a duck, then it must be a duck
With Composer:
composer require alexeyyashin/ducktyping
Without Composer:
- Copy repository files whereever you need
- Include autoload.php
include_once 'ducktyping-master/autoload.php';
Check methods implementation
duck_check(Duck::class)->implementing(Bird::class);
Will return true
if class Duck
implements all that exist in class Bird
(considering "static" modifier)
Note that you can use either class name (as string
) or object
both in duck_check
function and implementing
method
$duck = new Duck;
$bird = new Bird;
duck_check($duck)->implementing($bird);
Check single method existence
duck_check(Duck::class)->hasMethod('fly', $check_static)
Let's start with some basic independent classes
class Animal
{
public function run() {}
}
class Plant
{
public function growLeaves() {}
}
Then add some child class
class Bird extends Animal
{
public function fly() {}
}
It's obvious that
var_dump(new Bird instanceof Animal); // bool(true)
But if we add some independent class
class Duck
{
public function run() {}
public function fly() {}
public function quackle() {}
}
we will get
var_dump(new Duck instanceof Bird); // bool(false)
despite the fact it can both "run" and "fly" just because class Duck
doesn't extend class Bird
.
To check this by duck typing (Wiki) we can see if class Duck
has all
the methods from class Bird
using ducktyping
var_dump(duck_check(Duck::class)->implementing(Bird::class)); // bool(true)
// BUT, Duck does not have "growLeaves" method, so
var_dump(duck_check(Duck::class)->implementing(Plant::class)) // bool(false)
Multiple class implementation bonus
class Bulbasaur extends Pokemon
{
public static $link = "https://en.wikipedia.org/wiki/Bulbasaur";
public function run() {}
public function growLeaves() {}
public function fight() {}
}
$check = duck_check(new Bulbasaur);
$check->implementing(Pokemon::class) // true - because of inheritance
$check->implementing(Animal::class) // true - because of "run" method
$check->implementing(Plant::class) // true - because of "growLeaves" method
$check->implementing(Bird::class) // false - because of "fly" method absence
I wonder wheter we should check also public properties of testing classes/objects or not. So I need to uncomment that moment or remove it.
May be method signatures check will be added.