当使用多态时,如何让PHP代码知道传递给它的特定类子类型?

Den*_*nis 5 php oop polymorphism dynamic-typing

我有一个名为Assembly隐藏底层产品实现的类. ProductA可以有一套吸气剂,ProductB可以有另一套吸气剂.

虽然PHP非常宽容,如果我不混淆产品和吸气剂,我的代码会起作用,但是当我搞砸并填充AssemblyProductA,没有提供保护,但是后来使用了getter ProductB.

此外,我的IDE确实知道来自任何一个类的方法,因此当我Assembly使用其中任何一个的getter 工作时,没有提供自动完成Product.

我想要更多的防弹代码,一个Assembly 知道知道Product它当前托管哪个子类型的代码.有办法吗?

以下示例

class Assembly
{
    private $product;

    public function setProduct(Product $product) {
        $this->product = $product;
    }

    public function getA() {
        return $this->product->getA();
    }

    public function getB() {
        return $this->product->getB();
    }
}

class Product { }

class ProductA extends Product
{
    public function getA() {
        return "A";
    }
}

class ProductB extends Product
{
    public function getB() {
        return "B";
    }
}

//set assembly
$assembly = new Assembly();

//define product sub-type
$product = new ProductB();

//place product into assembly
$assembly->setProduct($product);

//assembly has no clue which subtype it has 
print $assembly->getB(); // "B"
print $assembly->getA(); // prints nothing
Run Code Online (Sandbox Code Playgroud)

接口建议

interface CompositeProductInterface
{
    public function getA();
    public function getB();
}

//update code in Assembly to:
public function setProduct(CompositeProductInterface $product)
{
    $this->product = $product;
}
Run Code Online (Sandbox Code Playgroud)

这让我在我的IDE中自动完成,这很好,但不能解决我的其他问题.此外,我将一些东西拼凑成一个单一的"复合"产品有点怪异......这看起来更像是一种解决方法.在我的具体情况下,我有两个非常相似的产品,在一些微小的东西,如一些属性上有所不同.

真实世界的例子

产品型号A和B都有一个工程图,其中列出了用于识别各种产品尺寸的变量.两种产品的命名尺寸相似.例如,产品A上的M1表示产品B上的相同物理尺寸.但是,产品A具有产品B上不存在的特征,反之亦然.

如果仍然感觉太假设,实际图纸上的实际尺寸列为B2B3.这些尺寸(B2,B3)不存在于其他产品型号上.我希望能够使用汇编构造列出图形上的变量,包括M1,B2,B3等.我可以这样做

print $assembly->getM1(); //works for both products
print $assembly->getB2(); //works for one product only
print $assembly->getB3(); //same as above
Run Code Online (Sandbox Code Playgroud)

目标

目标是让一个类(程序集)负责列出命名维度变量,每个产品只知道自己.所以

  • 汇编说"我知道我要列出的命名变量(M1,B2,B3),无论产品型号如何"
  • 产品A说"我只知道我包含的内容.我包含命名的维度A.我不知道B是什么,也不关心
  • 产品B说"我只知道B"......

mrh*_*rhn 1

我认为这不是正确的解决方案,但您所要求的可以通过以下方式实现。

get_class($product);
Run Code Online (Sandbox Code Playgroud)

会告诉你$product是哪个班级。这将导致以下代码:

private $product;
private $productClass;

public function setProduct(Product $product) {
    $this->product = $product;
    $this->productClass = get_class($product);
}
Run Code Online (Sandbox Code Playgroud)

或者:

public function getProductClass(){
    return get_class($this->$product);
}
Run Code Online (Sandbox Code Playgroud)

这可能会导致类似于以下内容的检查:

public function getA() {
    if($this->productClass === "ProductA")
        return $this->product->getA();
}
Run Code Online (Sandbox Code Playgroud)

正如以下文献中所记载的:

http://php.net/manual/en/function.get-class.php