根据 PHP 中的对象 属性 值动态实现接口?
Dynamically implement interface based on object property value in PHP?
假设我们有一个 Dog
class 和一个 Category
class 可以分配狗。
class Dog {
function categories() {} // Return the categories of the dog.
}
class Category {
function dogs() {} // Return the dogs under this category.
}
狗可以分为 'pet' 和 'shepherd' 类别。当分配给 'pet' 类别时,它是 'pet dog' 并且 'shepherd'.
也是如此
宠物狗和牧羊犬有不同的属性和功能。但是,一只狗可以同时是 'pet dog' 和 'shepherd dog'.
我可以想象 'pet dog' 和 'shepherd dog' 有不同的界面,例如
interface Huggable {
function hug();
}
interface Trainable {
function train();
}
理想情况下,当狗被分配到'pet'类别时,它实现Huggable
接口,如果它被分配到'shepherd'类别,它实现Trainable
类别.
可能吗?
正如我评论的那样,无法使用 PHP 本机实现此功能。
但是您可以使用装饰器来实现一些东西,例如。
愚蠢的decorator方法:
你有你的待装修class:
class Animal {
protected $categories = [];
public function getCategories() {
return $this->categories;
}
public function addCategory( string $category ) {
// we should check the animal doesn't already belong to this category
$this->categories[] = $category;
}
}
你的接口,Trainable
和 Huggable
:
interface Trainable {
function train();
}
interface Huggable {
// see https://github.com/php-fig/fig-standards/blob/master/proposed/psr-8-hug/psr-8-hug.md
function hug() : bool;
}
一个实现 Trainable 并将特定类别添加到装饰实例的装饰器:
class PetDecorator extends Animal implements Trainable {
public function __construct( Animal $animal ) {
$this->categories = $animal->getCategories();
$this->addCategory('pet');
}
public function train() {
echo "I'm housebroken!\n";
}
}
还有另一个 FluffyDecorator
实现了 Huggable
class FluffyDecorator extends Animal implements Huggable {
public function __construct( Animal $animal ) {
$this->categories = $animal->getCategories();
$this->addCategory('loveBear');
}
public function hug( ) :bool {
echo "Much hug!\n";
return true;
}
}
最后,你会这样使用它:
$fido = new Animal();
$fidoPet = new PetDecorator($fido);
$fidoPet->train();
// I'm housebroken!
print_r($fidoPet->getCategories());
/*
Array
(
[0] => pet
)
*/
$fidoLove = new FluffyDecorator($fidoPet);
// Much hug!
$fidoLove->hug();
print_r($fidoLove->getCategories());
/*
Array
(
[0] => pet
[1] => loveBear
)
*/
"Dogs" 和 "Categories" 之间的多对多关系我留给你。这是一个单独的问题,可以通过许多不同的方式处理。
假设我们有一个 Dog
class 和一个 Category
class 可以分配狗。
class Dog {
function categories() {} // Return the categories of the dog.
}
class Category {
function dogs() {} // Return the dogs under this category.
}
狗可以分为 'pet' 和 'shepherd' 类别。当分配给 'pet' 类别时,它是 'pet dog' 并且 'shepherd'.
也是如此宠物狗和牧羊犬有不同的属性和功能。但是,一只狗可以同时是 'pet dog' 和 'shepherd dog'.
我可以想象 'pet dog' 和 'shepherd dog' 有不同的界面,例如
interface Huggable {
function hug();
}
interface Trainable {
function train();
}
理想情况下,当狗被分配到'pet'类别时,它实现Huggable
接口,如果它被分配到'shepherd'类别,它实现Trainable
类别.
可能吗?
正如我评论的那样,无法使用 PHP 本机实现此功能。
但是您可以使用装饰器来实现一些东西,例如。
愚蠢的decorator方法:
你有你的待装修class:
class Animal {
protected $categories = [];
public function getCategories() {
return $this->categories;
}
public function addCategory( string $category ) {
// we should check the animal doesn't already belong to this category
$this->categories[] = $category;
}
}
你的接口,Trainable
和 Huggable
:
interface Trainable {
function train();
}
interface Huggable {
// see https://github.com/php-fig/fig-standards/blob/master/proposed/psr-8-hug/psr-8-hug.md
function hug() : bool;
}
一个实现 Trainable 并将特定类别添加到装饰实例的装饰器:
class PetDecorator extends Animal implements Trainable {
public function __construct( Animal $animal ) {
$this->categories = $animal->getCategories();
$this->addCategory('pet');
}
public function train() {
echo "I'm housebroken!\n";
}
}
还有另一个 FluffyDecorator
实现了 Huggable
class FluffyDecorator extends Animal implements Huggable {
public function __construct( Animal $animal ) {
$this->categories = $animal->getCategories();
$this->addCategory('loveBear');
}
public function hug( ) :bool {
echo "Much hug!\n";
return true;
}
}
最后,你会这样使用它:
$fido = new Animal();
$fidoPet = new PetDecorator($fido);
$fidoPet->train();
// I'm housebroken!
print_r($fidoPet->getCategories());
/*
Array
(
[0] => pet
)
*/
$fidoLove = new FluffyDecorator($fidoPet);
// Much hug!
$fidoLove->hug();
print_r($fidoLove->getCategories());
/*
Array
(
[0] => pet
[1] => loveBear
)
*/
"Dogs" 和 "Categories" 之间的多对多关系我留给你。这是一个单独的问题,可以通过许多不同的方式处理。