rfc:generics

This is an old revision of the document!


PHP RFC: Introduce generics into PHP

Introduction

Many languages, including hack by now, support generics, which for instance allow to create and typehint for specialized collections without the need to implement such a collection for every single entity. This RFC proposes the introduction of generics into PHP. Adding generic support to existing collections, e.g. in SPL, may be part of another RFC.

Generics offer a great way of avoiding duplicate code, where many classes only differ in the accepted variable types. The most prominent example are collections, like simple lists, priority queues, heaps and such. Instead of having to implement such a collection for every object which requires one, you can simply create a generic collection and have it used for all object.

Proposal

A class is considered generic when it has one or more types defined. The defined types can be used in both method parameter type hinting and return type hinting.

class Entry<KeyType, ValueType>
{
    protected $key;
    protected $value;
 
    public function __construct(KeyType $key, ValueType $value)
    {
        $this->key   = $key;
        $this->value = $value;
    }
 
    public function getKey(): KeyType
    {
        return $this->key;
    }
 
    public function getValue(): ValueType
    {
        return $this->value;
    }
}
 
$entry = new Entry<int, string>(1, 'test'); // Valid
$entry = new Entry(1, 'test'); // Throws an EngineException about missing types

Functions and methods are able to type hint against specific variations of a given class:

function foo(Entry<int, string> $entry)
{
    // …
}
 
foo(new Entry<int, string>(1, 'test')); // Valid
foo(new Entry<int, int>(1, 2)); // Throws an EngineException about invalid argument

A generic class can also force a type to extend a specific class or implement a specific interface:

class Bazz<Foo : \Bar>
{
}

Beside generic classes, there are also generic methods. These can be quite useful if you have static constructor methods on your class:

class SomeList<Bar>
{
    public static function <Baz> SomeList<Baz> fromArray(array $a)
    {
        $list = new static<Baz>();
        // Fill list from $a
        return $list;
    }
}
 
$list = SomeList<int>::fromArray([1, 2]);

Backward Incompatible Changes

No BC breaks are expected from this proposal.

Proposed PHP Version(s)

This proposal aims for PHP 7.1.

Proposed Voting Choices

For this proposal to be accepted, a 2/3 majority is required.

Patches and Tests

No patch has been written for this yet. As I'm not a C-coder myself, I encourage others to write a patch based on this proposal.

References

rfc/generics.1441051493.txt.gz · Last modified: 2017/09/22 13:28 (external edit)