alexeyyashin/ducktyping

Simple duck-typing implementation for PHP

v1.0.1 2020-12-02 12:42 UTC

This package is auto-updated.

Last update: 2024-05-29 04:09:14 UTC


README

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

Installation

With Composer:

composer require alexeyyashin/ducktyping

Without Composer:

  • Copy repository files whereever you need
  • Include autoload.php
include_once 'ducktyping-master/autoload.php';

Basic usage

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)

Explanation

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

Further

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.