条件参数和返回类型声明(又名类型提示)

Posted

技术标签:

【中文标题】条件参数和返回类型声明(又名类型提示)【英文标题】:Conditional argument and return type declarations (aka type hinting) 【发布时间】:2018-10-21 20:54:51 【问题描述】:

我有以下抽象类,它具有Entity 对象的参数和返回类型声明。 Entity 是一个虚构的占位符,实际上应该声明它们以显示返回 User(或扩展 EntityServices 指定的任何实际类)。

是否可以让EntityServices 使用User 的类型声明而不是Entity 而无需在User 类中复制脚本?如果是这样,怎么做?如果没有,是否有一种解决方法可以让脚本至少在某种级别的类型声明功能中被重用?

<?php
namespace NotionCommotion;
abstract class EntityService

    //Constructor in child

    public function get(int $id): ?Entity 
        //Will return User or Bla argument based on the extending class
        return $this->mapper->read($id);
    

    public function create(array $data): Entity 
        //Will return User or Bla argument based on the extending class
        if (!$this->validator->load($this->getValidationFile())->isValid($data)) throw new UserValidationError($this->validator, $data);
        $this->doTransation(function()$this->mapper->add($data););
    

    public function update(array $data, int $id): Entity 
        //Will return User or Bla argument based on the extending class
        if (!$this->validator->load($this->getValidationFile())->nameValueisValid($data)) throw new UserValidationError($this->validator, $data);
        $this->doTransation(function()$this->mapper->update($data););
    

    public function delete(int $id): void 
        $this->mapper->delete($id);
    

    public function whatever(Entity $whatever) 
        //Requires User or Bla argument based on the extending class
    

    protected function doTransation($f)
        try 
            $f();
            $this->pdo->commit();
         catch (\PDOException $e) 
            $this->pdo->rollBack();
            throw($e);
        
    

    abstract protected function getValidationFile();

UserServices

<?php
namespace NotionCommotion\User;
class UserService extends \EntityService

    public function __construct(UserMapper $userMapper, \Validator $validator, Foo $foo) 
        $this->mapper=$userMapper;
        $this->validator=$validator;
        $this->foo=$foo;
    

BlaServices

<?php
namespace NotionCommotion\Bla;
class BlaService extends \EntityService

    public function __construct(BlaMapper $blaMapper, \Validator $validator) 
        $this->mapper=$blaMapper;
        $this->validator=$validator;
    

【问题讨论】:

Is this possible? 什么应该是可能的? 不清楚你想要什么。 我将编辑原始范围以更好地描述。谢谢 你说的是covariance and contravariance吗? @GabrielHeming 我不这么认为。我希望使扩展父抽象类中的方法更窄,并匹配扩展子类的方法。 【参考方案1】:

你不能在 PHP 中做到这一点。

一般来说,一种明智的做法是使用继承或接口。

例如,继承:

class Animal 

class Cat extends Animal 

class Service 
  public function reproduce() : Animal 
    return new Animal();
  



class ImprovedService extends Service 
  public function reproduce() : Animal 
    return new Cat();
  

您无法更改 reproduce() 定义,但您可以返回原始返回定义的后代。

或者使用接口,例如:

interface Mammal 
  public function makeSound() : string;


class Dog implements Mammal 
  public function makeSound() : string 
    return "Bark!";
  


class GenericMammal implements Mammal 
  public function makeSound() : string 
    return "???";
  


class Service 
  public function test() : Mammal 
    return new GenericMammal();
  



class ImprovedService extends Service 
  public function test() : Mammal 
    return new Dog();
  

每种方法都有优点和缺点,因此您需要看看哪种方法更适合您的情况。

【讨论】:

其实界面方案好像不太适用。它适用于string,因为所有类中的方法都是这样声明的。我希望我可以在父类中关闭声明,只将它包含在接口中,但是,这会导致错误。 @user1032531 如果一个类实现了一个接口,它需要完全实现它。如果您不想被限制为返回类型,只需在接口声明中省略它即可。 是的,我刚刚阅读了文档:The class implementing the interface must use the exact same method signatures as are defined in the interface. Not doing so will result in a fatal error. 我可以在界面中省略它们,但这样就失去了界面的一些好处。由于其他人不认为这是一个问题,我想我并没有真正理解应该如何使用它们。 不过,这是实现您想要的唯一方法。剩下的就是正确设计您的应用程序。 :)

以上是关于条件参数和返回类型声明(又名类型提示)的主要内容,如果未能解决你的问题,请参考以下文章

PhpStorm - 有没有办法将 PHPDoc 转换为类型提示并返回类型声明?

使用返回类型声明返回 NULL

当一个函数无返回值时,函数的类型应定义为啥

TypeScript:条件类型并使用布尔参数来控制返回类型

具有默认参数值的打字稿条件返回类型

基础函数的声明&返回值