Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can PHP code be made aware of specific class subtypes passed to it, when using polymorphism? [closed]

I have a class called Assembly that hides implementation of underlying products. ProductA can have one set of getters, ProductB can have another.

While PHP is quite forgiving and if I don't mix up Products and getters, my code will work, but there is no protection offered for when I do mess up and populate Assembly with ProductA, but then use a getter from ProductB.

Also, my IDE does know the methods from either class, so there is no auto-complete offered when I work inside Assembly with getters from either Product.

I want more bullet-proof code, one where Assembly knows or is aware of which Product subtype it currently hosts. Is there a way to do so?

Sample below

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

Interface Suggestion

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

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

This gives me autocomplete in my IDE, which is nice, but doesn't solve my other issues. Also I am a little eerie on mushing things together into a single "composite" product.... It seems more like a work-around. In my specific case I have two very similar products that differ on some minute things like a few properties.

Real World Example

Both Product models A and B have an engineering drawing that lists variables to identify various product dimensions. Named dimensions are similar across both products. For example, M1 on product A means the same physical dimension on product B. However, Product A has features not present on product B and vice versa.

If that still feels too hypothetical, the actual dimensions on the actual drawing are listed as B2, and B3. These dimensions (B2, B3) are not present on the other product model. I want to be able go use an assembly construct to list variables on the drawing, including M1, B2, B3, and so on. I could do so with

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

Goal

Goal is to have a single class (assembly) responsible for listing named dimension variables, and each product only know itself. So

  • Assembly says "I know everything about the named variables I want to list (M1, B2, B3), regardless of product model"
  • Product A says "I only know what I contain. I contain named dimension A. I don't know what B is nor do I care to
  • Product B says "I only know B" ...
like image 602
Dennis Avatar asked Nov 09 '22 01:11

Dennis


1 Answers

I do not feel this is the right solution, but what you ask for could be achieved in the following way.

get_class($product);

Will tell you which class $product is. Which would lead to the following code:

private $product;
private $productClass;

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

Or:

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

Which could leads to a check similar to:

public function getA() {
    if($this->productClass === "ProductA")
        return $this->product->getA();
}

As well documented in:

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

like image 198
mrhn Avatar answered Nov 15 '22 13:11

mrhn