Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
634 views
in Technique[技术] by (71.8m points)

php - Narrowing-down the return type of an implemented method

I'm trying to specify two interfaces for class A that returns instances of class B, and for class B itself.

I'm declaring return types on the interface.

Say I've got two interfaces.

Some kind of RepositoryInterface, that has a get() method that returns an object implementing the ElementInterface

<?php

namespace AppContracts;

interface RepositoryInterface {

    public function get( $key ) : ElementInterface;

}

And an element interface:

<?php

namespace AppContracts;

interface ElementInterface { }

Now, my implementation of the repository declares a return-type that is a specific class MyElement.

<?php

namespace AppRepositories;

class MyRepository implements RepositoryInterface {

    public function get( $key ) : MyElement {
        // ...
    }

}

Where MyElement is some class implementing ElementInterface.

... this results in a fatal error:

Declaration of MyRepository::get( $key ): MyElement must be compatible with RepositoryInterface::get( $key ): ElementInterface

If I would not specify the return types on the interface, this would work perfectly fine. Yet, I want to constrain the type of class returned by any class implementing the RepositoryInterface.

  1. Is it true that this is not possible in PHP 7.1?
  2. If this is indeed not possible, is that because my pattern is incorrect?
  3. How could I declare the return type of my interface methods without specifying an actual implementation of this type.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is not possible with any version of PHP lower than 7.4.

If your interface contains:

public function get( $key ) : ElementInterface;

Then your class needs to be:

class MyRepository implements RepositoryInterface {

    public function get( $key ) : ElementInterface {

        returns new MyElement();
        // which in turn implements ElementInterface
    }
}

The declaration of a class implementing an interface has to match exactly the contract laid out by the interface.

By declaring that it has to return a particular interface instead of an specific implementation, you are giving you leeway on how to implement it (now you could return MyElement or AnotherElement as long as both implemented ElementInterface); but the method declaration has to be the same anyway.

See it working here.


Starting with PHP 7.4, due to be released in November 2019, covariance will be supported for return types. By then, this would work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...