2016-03-20 25 views
0

我正在學習PHP,剛剛開始使用中間級別。下面是類層次結構 -在PHP中重載多級繼承中的函數,但沒有任何參數

FamilyTree 
    | 
    | 
Grandparents 
    | 
    | 
Parents 

Parents呼籲$dob其餘額外的屬性從Grandparents

我能超載​​,因爲它們在參數的數目不同繼承的,我怎麼超載display_values()因爲它沒有任何爭論?

這是代碼:

<?php 

class FamilyTree { 

    protected $name; 
    protected $sex; 
    protected $married; 
    protected $number_of_kids; 

    public function display_values() { 
     echo $this->name   . "<br />"; 
     echo $this->sex    . "<br />"; 
     echo $this->married   . "<br />"; 
     echo $this->number_of_kids . "<br />"; 
    } 
} 

class Grandparents extends FamilyTree { 

    public function set_values($name, $sex, $married, $number_of_kids) { 
     $this->name   = $name; 
     $this->sex   = $sex; 
     $this->married  = $married; 
     $this->number_of_kids = $number_of_kids; 
    }  
} 

class Parents extends Grandparents { 

    private $dob; 

    public function __call($function_name, $arguments) { 
     if($function_name == 'set_values' && count($arguments) == 5) { 
      $this->$name   = $name; 
      $this->sex   = $sex; 
      $this->married  = $married; 
      $this->number_of_kids = $number_of_kids; 
      $this->dob   = $dob; 
     } 
    } 
} 

$gp = new Grandparents(); 
$gp->set_values("James", "Male", 'yes', 5); 

$p = new Parents(); 
$p->set_values("Samuel", "Male", 'yes', 2, '2/5/1974'); 

$gp->display_values(); 
+1

那麼如果您只是將'public function display_values()'添加到'Parents'類會發生什麼? –

+0

@u_mulder,如果我這樣做,那麼它不會打印任何** $ this-> dob ** –

回答

2

對不起,令您失望,但您在「重載」該方法時未成功。

如果你把你的執行細看如果__call

public function __call($function_name, $arguments) { 
    if($function_name == 'set_values' && count($arguments) == 5) { 
     $this->$name   = $name; 
     $this->sex   = $sex; 
     $this->married  = $married; 
     $this->number_of_kids = $number_of_kids; 
     $this->dob   = $dob; 
    } 
} 

你會發現,

  • $this->$name應該$this->name
  • $name$sex$married$number_of_kids$dob是全部未定義,而應該是$arguments[0]$arguments[4]

但是您的__call實現根本不會被調用,因爲PHP simply discards too many arguments to user-defined functions

你可以做的,而不是,是重寫功能,並調用父類的實現與parent::

public function set_values($name, $sex, $married, $number_of_kids, $dob = '') { 
    parent::set_values($name, $sex, $married, $number_of_kids); 
    $this->dob = $dob; 
} 

我只是初始化$dob爲空字符串,因爲它會默認爲NULL否則。
作爲一個側面說明,如果你想提供一個新的實現,需要參數比原來的,你也可以做到這一點與默認參數:

public function set_values($name, $sex, $married, $number_of_kids = 0) { 
    parent::set_values($name, $sex, $married, $number_of_kids); 
} 

它然後可以用任意3名爲或4個參數。

對於更復雜的組合,爲每個參數聲明新實現(爲了使其與父實現兼容)並使用func_get_args來處理或重定向呼叫。

重載display_values簡單不過,因爲參數的數量是一樣的:

public function display_values() { 
    parent::display_values(); 
    echo $this->dob . "<br />"; 
} 

所以滿,你的代碼應該是這樣的:

<?php 

class FamilyTree { 

    protected $name; 
    protected $sex; 
    protected $married; 
    protected $number_of_kids; 

    public function display_values() { 
     echo $this->name   . "<br />"; 
     echo $this->sex    . "<br />"; 
     echo $this->married   . "<br />"; 
     echo $this->number_of_kids . "<br />"; 
    } 
} 

class Grandparents extends FamilyTree { 

    public function set_values($name, $sex, $married, $number_of_kids) { 
     $this->name   = $name; 
     $this->sex   = $sex; 
     $this->married  = $married; 
     $this->number_of_kids = $number_of_kids; 
    } 
} 

class Parents extends Grandparents { 

    private $dob; 

    public function set_values($name, $sex, $married, $number_of_kids, $dob = '') { 
     parent::set_values($name, $sex, $married, $number_of_kids); 
     $this->dob = $dob; 
    } 

    public function display_values() { 
     parent::display_values(); 
     echo $this->dob . "<br />"; 
    } 
} 

$gp = new Grandparents(); 
$gp->set_values("James", "Male", 'yes', 5); 

$p = new Parents(); 
$p->set_values("Samuel", "Male", 'yes', 2, '2/5/1974'); 

$gp->display_values(); 
$p->display_values(); 
0

對於方法重載的簽名和方法名應該是相同的。沒有這兩個,它不會被視爲方法重載。在這種情況下,不是超載,而是一種單獨的方法。您可以簡單地通過此display_values($ name,$ sex,$ married,$ number_of_kids)重載並設置所有值

+0

它不需要我提到它的任何參數。 –

0

除非我誤解你,在這種情況下,您不會通過父類中的__call重載set_values。要超載,該方法必須無法訪問。

class Parents extends Grandparents { 

private $dob; 

public function __call($function_name, $arguments) { 
    echo 'called'; 
    if($function_name == 'set_values' && count($arguments) == 5) { 
     $this->$name   = $name; 
     $this->sex   = $sex; 
     $this->married  = $married; 
     $this->number_of_kids = $number_of_kids; 
     $this->dob   = $dob; 
    } 
} 

}

這將不打印 '調出的' $ P->函數set_values( 「塞繆爾」, 「男性」, '是',2, '1974年2月5日');.

要覆蓋父方法必須是人跡罕至的方法,沒關係有關參數的數目,見下面的例子:

<?php 

class FamilyTree { 

    protected $name; 
    protected $sex; 
    protected $married; 
    protected $number_of_kids; 

    private function display_values() { 
     echo $this->name   . "<br />"; 
     echo $this->sex    . "<br />"; 
     echo $this->married   . "<br />"; 
     echo $this->number_of_kids . "<br />"; 
    } 
} 

class Grandparents extends FamilyTree { 

    private function set_values($name, $sex, $married, $number_of_kids) { 
     $this->name   = $name; 
     $this->sex   = $sex; 
     $this->married  = $married; 
     $this->number_of_kids = $number_of_kids; 
    } 

    private function drawMe($a) 
    {} 

} 

class Parents extends Grandparents { 

    private $dob; 

    public function __call($function_name, $arguments) { 
     echo 'Args: ' . count($arguments); 
     echo ' | Function name: ' . $function_name; 
     if($function_name == 'set_values' && count($arguments) == 5) { 
      $this->$name   = $name; 
      $this->sex   = $sex; 
      $this->married  = $married; 
      $this->number_of_kids = $number_of_kids; 
      $this->dob   = $dob; 
     } 
    } 
} 


$p = new Parents(); 
$p->display_values(); 
echo '<br><br>'; 
$p->set_values("Samuel", "Male", 'yes', 2, '2/5/1974'); 

此打印:

參數數量:0 |函數名稱:display_values

參數:5 |函數名稱:set_values