2017-06-01 59 views
1

額外的參數考慮以下情況:處理在PHP

class Factory { 
    private $x = 1; 
    private $y = 2; 
    private $z = 3; 

    public function create(string $instance) { 
     return new $instance($this->x, $this->y, $this->z); 
    } 
} 

class A { 
    private $x; 

    public function __construct ($x) { 
     $this->x = $x; 
    } 

    public function display() { 
     echo "<pre>$this->x</pre>"; 
    } 
} 

class B { 
    private $x; 
    private $y; 
    private $z; 

    public function __construct ($x, $y, $z) { 
     $this->x = $x; 
     $this->y = $y; 
     $this->z = $z; 
    } 

    public function display() { 
     echo "<pre>$this->x</pre>"; 
     echo "<pre>$this->y</pre>"; 
     echo "<pre>$this->z</pre>"; 
    } 
} 

$factory = new Factory; 

$a = $factory->create("A"); 
$a->display(); 

$b = $factory->create("B"); 
$b->display(); 

正如你所看到的,工廠將始終提供3 arguments時,它會創建一個新的實例。但是在class A中,構造函數只需要1 argument。由於php沒有通常的方法重載,所以這不會導致問題。但爲了安全起見,我要補充的參數列表參數爲class Acontructor是這樣的:

public function __construct ($x, ... $ignore) { ... } 

趕上那些無謂的爭論,因爲我知道它每次會得到這些額外的參數。還是現有的代碼是足夠的?

+0

嘗試使用http://php.net/manual/en/function.func-get-args.php爲類A,如果你需要參數 - 如果不能保持原樣。同樣在你的工廠中,你應該使用類的名字而不是變量,如果你把'a'而不是'A'會發生什麼? Imho在建立你的班級之前最好檢查一下。 – Edwin

+0

你會用'$ ignore'做什麼? –

+0

你可以使用func_num_args來驗證參數的數量來處理它http://php.net/manual/en/function.func-num-args.php –

回答

1

如果您傳遞的變量超過函數定義中所需的變量,那些額外變量將被忽略(示例:https://3v4l.org/fNfAQ)。

但是,這可能是一個跡象,你試圖對這個特定的工廠做太多的事情,並且使用DI容器可能會有更好的結果。

或者您可能需要擁有單獨的工廠,以創建具有不同依賴關係的實例,而不是製造單一的「make everything」工廠。

+0

確實,不同的工廠更好,但如果我有一堆類似的B - Z類,A是唯一的例外,它就沒用了。但是因爲他們被忽略了,我會堅持現有的代碼。 –

0

而不是傳遞單獨的參數,您可以爲所有的構造函數使用關聯數組。

class A { 
    private $x; 

    public function __construct ($params) { 
     $this->x = $params['x']; 
    } 

    public function display() { 
     echo "<pre>$this->x</pre>"; 
    } 
} 

class B { 
    private $x; 
    private $y; 
    private $z; 

    public function __construct ($params) { 
     $this->x = $params['x']; 
     $this->y = $params['y']; 
     $this->z = $params['z']; 
    } 

    public function display() { 
     echo "<pre>$this->x</pre>"; 
     echo "<pre>$this->y</pre>"; 
     echo "<pre>$this->z</pre>"; 
    } 
} 

則工廠可以這樣做:

public function create($instance) { 
    return new $instance(array('x' => $this->x, 'y' => $this->y, 'z' => $this->z)); 
} 
+0

這會違反[POLA](https://en.wikipedia.org/wiki/Principle_of_least_astonishment),因爲您無法知道構造函數中類實例需要什麼參數,而無需實際讀取該構造函數的代碼。 –

+0

@tereško它是否真的比期望所有的構造函數都以相同的固定順序接受參數更糟糕,除了有些是可選的? – Barmar

+0

我猜他可以使用普通數組:'new $ instance(array($ this-> x,$ this-> y,$ this-> z))',構造函數可以使用他們想要的任何數組元素。 – Barmar