简体   繁体   中英

PHP inheritance and different parameters in childs

I'm trying to create something similar to generics in PHP. I want other programmers to be able to create their own supported data types, so I used design patterns called Fasade, Adapter and Factory.

I have a main class that is a factory that creates concrete objects that share a uniform interface.

Factory:

class ListFactory
{
    public function __construct(private readonly array $listClasses) {}

    public function create(string $type)
    {
        return new ($this->listClasses[$type]);
    }
}

The $listClasses variable is ideally injected via DI and contains all classes that implement the ListInterface in the format ['type' => 'className'] ...

So now I have an interface that defines only one method so far:

ListInterface:

interface ListInterface
{
    public function add($item): static;
}

and then so far I have two concrete classes that implement this interface:

IntList:

class IntList implements ListInterface
{
    private array $value = [];

    public function add($item): static
    {
        if (!is_int($item)) { /* throw exception */}
        $this->value[] = $item;
        return $this;
    }
}

String List:

class StringList implements ListInterface
{
    private array $value = [];

    public function add($item): static
    {
        if (!is_strnig($item)) { /* throw exception */}
        $this->value[] = $item;
        return $this;
    }
}

the question is how to make it so that I don't have to validate the data type with if, but I could write, for example, in the StringList class the add function like this:

public function add(string $item): static
{
    $this->value[] = $item;
    return $this;
}

If I try to do it now, I get an error like that add method in the StringList class must be compatible with the add method inside the ListInterface

Thanks

The signature must match as your error message stated. To make it easy for every add function of that interface you could use a trait and do the type checking in there.

interface ListInterface {
    public function add(mixed $item): static;
}

trait ListTrait {
    public function add(mixed $item): static
    {
        switch(gettype($item)) {
            case 'integer':
                if(!$this instanceof IntList) throw new Exception("Int expected");
                break;
            case 'string':
                if(!$this instanceof StringList) throw new Exception("String expected");
                break;
        }
        $this->value[] = $item;
        return $this;
    }
}

class IntList implements ListInterface
{
    use ListTrait;
    private array $value = [];
}

class StringList implements ListInterface
{
    use ListTrait;
    private array $value = [];
}

Example usage

$i = new IntList();
$i->add(123);
$i->add("123"); // Exception!

$s = new StringList();
$s->add("123");
$s->add(123); // Exception!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM