是的,如果你的代碼不是開源的,否則沒有。
不檢查對象的實例並不能確保方法getUser()
返回的對象將擁有您所期望的所有方法(例如:getUsername()
)。
如果您查看Controller.php中的getUser()
方法,它不一定會返回用戶對象。事實上,您可以設置Symfony2防火牆,getUser()
將返回不同實例的不同對象。
承認我們有一個接口UserInterface
,它定義了getUsername()
。
在以下代碼中,我們的用戶對象不執行UserInterface
。
$user = $this->getUser();
if (!is_object($user)) {
$user->getUsername();
}
此代碼將拋出一個錯誤,因爲getUsername()
不會在對象上存在,而不是代碼應該是以下幾點:
$user = $this->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
$user->getUsername();
}
如果用戶對象沒有實現正確的接口,則代碼不會出錯,因爲它不會被執行。
避免檢查類似下面的
$user = $this->getUser();
if (!is_object($user) || !$user instanceof User) {
$user->getRoles();
}
對象如果有人擴展了用戶對象,然後if語句將不再執行,因爲$user
不會是User
實例,但說ExtendedUser
即使它有所有你需要的方法。
使用接口的另一個優點是可以在對象上實現多個接口。
class A implements C {}
class B extends A implements C, D {}
interface C {}
interface D {}
$nA = new A();
$nB = new B();
$nA instanceof A; // true - instance of A
$nA instanceof B; // false - pretty obvious, no relationship with B
$nA instanceof C; // true - A implements C
$nA instanceof D; // false - A does not implement D
$nB instanceof A; // false - B is not an instance of A
$nB instanceof B; // true - instance of B
$nB instanceof C; // true - A implements C, that's the key:
// both A and B implements C but B is not an
// instance of A.
$nB instanceof D; // true - A implements D
TLDR;接口是設置期望並避免重大難題的好方法。
當您通讀代碼時,您可以快速識別傳遞的對象的類型。如果有人更改了代碼,它將顯示一個有意義的錯誤,或者會優雅地降級(在這種情況下,用戶將被拒絕訪問)。
這不是爲了快速交換類,而是爲了確保這些類必須實現所需的方法,以便現有代碼可以在需要時調用這些方法,並且不需要破解源代碼以滿足您的需求自己的類 – DarkBee
接口不允許多重繼承,在PHP中沒有多繼承。 – Stev