Php 条件参数和返回类型声明(又称类型暗示)
我有以下抽象类,它具有Php 条件参数和返回类型声明(又称类型暗示),php,oop,type-hinting,Php,Oop,Type Hinting,我有以下抽象类,它具有实体对象的参数和返回类型声明Entity是一个虚构的占位符,实际上它们应该声明为显示返回的User(或者扩展EntityServices的实际类指定的任何内容) 是否可以让EntityServices使用User的类型声明,而不是Entity,而不复制User类中的脚本?如果是,怎么做?如果没有,是否有一种变通方法允许脚本至少在某种级别的类型声明功能下重用 <?php namespace NotionCommotion; abstract class EntitySe
实体
对象的参数和返回类型声明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();
}
BlaServices
class
<?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;
}
}
<?php
namespace NotionCommotion\Bla;
class BlaService extends \EntityService
{
public function __construct(BlaMapper $blaMapper, \Validator $validator) {
$this->mapper=$blaMapper;
$this->validator=$validator;
}
}
在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();
}
}
您不能更改repearch()
定义,但可以从原始返回定义返回子体
或者使用接口,例如:
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();
}
}
每种方法都有其优缺点,因此您需要看看哪种方法对您的案例更有意义。这可能吗
?什么是可能的?不清楚您想要什么。我将编辑原始范围以更好地描述。谢谢你在说什么?@GabrielHeming我不这么认为。我希望使扩展父抽象类中的方法更窄,并与扩展子类中的方法相匹配。实际上,接口解决方案似乎不适用。它与string
一起工作,因为所有类中的方法都是这样声明的。我希望可以在父类中禁用声明,而只在接口中包含声明,但是,这会导致错误。@user1032531如果类实现了接口,则需要完全实现它。如果您不想被限制为返回类型,只需在接口声明中省略它。是的,我刚刚阅读了文档:实现接口的类必须使用与接口中定义的方法签名完全相同的方法签名。不这样做将导致致命错误。
我可以在接口中省略它们,但这样会失去接口的一些好处。由于其他人不认为这是一个问题,我想我并不真正理解如何使用它们。不过,这是实现你想要的唯一方法。其余部分是关于正确设计应用程序的。:)