Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
596 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 Reply

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...