回答
Why doesn't PHP permit private constants?
在PHP常量是接口的部分和接口是公開的,始終(這是一個接口是什麼)。
還請參閱PHP Interfaces。
我很確定這是設計方面的原因。
關於在你的問題下的評論,有人想減少常量的可見性以稍後改變它們,我會說這聽起來更像是一個變量,而不是一個不改變它的值的常量。它是不變的。
TL,TR
什麼是不實現私有常量的理由?
這是一個很好的問題。
他們真的考慮過這個嗎?
我不知道。
當通過PHP內部郵件列表進行搜索時,我沒有發現任何關於此主題的內容。 除非內部的成員發言,否則我們永遠不會知道。
關於語言的歷史 - 有點1:1C的方法包裝,有些位來自Perl(regexp),有些位Java(oop) - 有可能這個想法彈出來,同時尋找新的語言特徵。
我會將「私人常量」的概念與VisualBasic或Java聯繫起來。我懷疑VB對PHP有什麼影響。 VB允許在「模塊」中定義「私有常量」 - 這是默認的訪問範圍。 Visual Basic不允許在接口和命名空間中使用常量(但PHP會)。
PHP可能包含來自Java的一些OOP概念,但有一個很大的區別:常量是Java中的變量。他們的訪問修飾符/可見性級別是:「公共,私人,最終和靜態」。私人常量聲明如下所示:
"private static final String MYCONST = "My Constant";
這是OOP - 故事結束。與此相比,PHP的常量訪問感覺更加黑客 - 但它更簡單,你仍然有手頭的解決方法。在PHP manual for Class Constants第一個評論是:
It may seem obvious, but class constants are always publicly visible. They cannot be made private or protected. I do not see it state that in the docs anywhere.
爲什麼這是明擺着的嗎? 「爲什麼一個班級默認公開而不是私人?」 也許,這是一種缺少語言功能,因爲並非所有班級成員都可以正確隱藏。 他是對的,當你從Java或VB到PHP時,這個問題就會彈出來。
讓我們來看看PHP spec。 PHP實現的當前狀態是:類常量總是公共的和靜態的。所以,一次又一次地贊成Facebook寫這樣的詳細文檔:作者考慮了不同的可視性或訪問控制級別。
讓我們來看看接口,類常量和知名度:
怎樣的概念「常量」,從「私有靜態」有什麼不同?
靜態變量可以改變,常數不能改變。 您不能將函數的運行時值分配給const(
const A = sprintf('foo %s', 'bar');
),而是分配給私有靜態變量。接口可能有常數 - 它們不能被覆蓋。
一個類可能有一個常量 - 可能會被繼承的類/接口覆蓋。
還有一種名爲「常量接口模式」的OOP模式 - 它描述了使用接口來定義常量,並使類實現該接口以實現對這些常量的方便的語法訪問。
提供了一個接口,以便您可以描述一組函數,然後隱藏實現類中的函數的最終實現。這使您可以更改功能的實施,而不必更改使用方法。存在接口來公開一個API。
通過在接口中定義常量並通過類實現接口,常量成爲API的一部分。實際上,您正在將實現細節泄漏到API中。這就是爲什麼有些人認爲這是一種反模式,其中包括Joshua Bloch(Java)。
現在,讓我們嘗試合併一些概念,看看它們是否合適。我們假設我們試圖避免上面的批評,然後您需要引入一個語法,它允許對常量進行有限訪問,但隱藏API中的常量。您可以通過可見性級別來訪問「訪問控制」:「公共,私人,受保護,朋友,敵人」。目標是防止包或類的用戶依賴於該包或類的實現的不必要細節。這完全是關於隱藏實現細節,對吧?
「接口」中的「私人常量」呢?
這實際上會解決上面的批評,對嗎? 但接口與「私人」的組合,沒有任何意義。這些概念是相反的。 這就是爲什麼界面不允許「私人」訪問/可見性水平。 而「接口」中的「私有」常量也是互斥的。
那麼在「類」中的「私人常量」呢?
class a {
/*private*/ const k = 'Class private constant k from a';
}
class b extends a
{
const k = 'Overridden private constant a::k with Class constant k from b';
const k_a = parent::k;
// fatal error: self-referencing constant
#const k_selfref = self::k . ' + ' . self::k_selfref;
// fatal error: "static::" is not allowed in compile-time constants
#const k_staticref = static::k;
}
// direct static access would no longer work, if private
// you need an instance of the parent class or an inheriting class instance
echo a::k;
echo b::k;
echo b::k_a;
$obj_b = new b;
echo $obj_b::k;
echo $obj_b::k_a;
有什麼好處?
該類中的私有常量不會暴露在API中。這是很好的OOP。
從外部訪問父常量將是類和/或繼承訪問。
echo a::k
,現在可以工作 - 可以用「致命錯誤:嘗試訪問沒有類實例或繼承的私有常量」。(這可能仍然僅在編譯時工作,如果沒有運行時間值賦值給一個常量。但我不知道這一個。)
是否有注意事項?
我們會失去常數的直接靜態訪問。
要求創建一個類的實例,只是爲了訪問常量而浪費資源。直接靜態訪問節省資源,而且很簡單。如果我們引入私人信息,那就失去了,訪問將被綁定到實例。
「私人常量」隱式是「私人靜態常量」。訪問操作符仍然是「::」。
可能的後續更改將切換到隱式非靜態常量。 這是BC休息。 如果將默認行爲切換爲非靜態,訪問運算符將從「::」更改爲「 - >」。 這建立了一個適當的OOP對象訪問常量,這與Java的「常量作爲具有訪問級別的變量」的概念是可比的。這將有點像這樣:http://3v4l.org/UgEEm。當常量被聲明爲「public static const」時,訪問運算符變爲靜態,對吧?
是效益好到足以實現它?
我不知道。它正在討論中。 我喜歡這兩種:常量靜態訪問,因爲它很簡單,並且「常量作爲變量」和適當的訪問級別的概念。
後多數民衆贊成實施,爲了節省資源,並保持持續快速,每個人都開始(重新)宣佈「公共靜態常量」,刪除該實例的要求和違反OOP)
而且BTW:發現HHVM溢出,同時試驗這個答案的代碼。
- 1. 爲什麼允許私人入口?
- 2. 爲什麼PHP不允許比較?
- 3. 爲什麼變量不允許綁定
- 4. 爲什麼正常變量不允許位域?
- 5. %爲什麼不允許
- 6. 爲什麼java允許私有字符串[] [] var []
- 7. 爲什麼GCC允許從私有嵌套類繼承?
- 8. 爲什麼允許靜態方法調用私有方法?
- 9. 爲什麼Windows允許創建私有堆?
- 10. 爲什麼PHP允許從其他實例調用私有方法?
- 11. 爲什麼允許內聯函數操作私有成員變量?
- 12. 發送允許訪問私有變量
- 13. 爲什麼python允許覆蓋內建常量?
- 14. 爲什麼Java不允許在類之外初始化變量或常量?
- 15. 爲什麼PHP私有類var不是私有的?
- 16. Java - 爲什麼數組常量不允許作爲Annotation屬性值?
- 17. 爲什麼header允許跨域不允許使用echo來輸出變量值?
- 18. 爲什麼java允許NPE
- 19. 什麼php配置變量不允許連接數組索引?
- 20. 爲什麼樣式表列不允許?
- 21. 爲什麼Java不允許以
- 22. 爲什麼CalendarProvider不允許寫入ExtendedProperties?
- 23. 爲什麼System.out.println(super)不允許?
- 24. 爲什麼不允許密碼驗證?
- 25. 爲什麼我的XMLHttpRequest不允許XSS?
- 26. 爲什麼不允許我調試
- 27. 爲什麼IDBKeyRange.only()不允許布爾值?
- 28. 爲什麼a,b = 1不允許?
- 29. 爲什麼C++不允許使用typeof?
- 30. 爲什麼sfinae如果constexpr不允許?
很難說爲什麼。希望其中一位PHP開發人員能夠順利通過。我認爲,自PHP 5.3以來,類常量才存在,所以也許它只是沒有實現*還*。我的猜測是,它不是一個非常有用的功能,因此在心願單中很低。保護方法和屬性對保護常量更有用。 – GolezTrol
@ AlexanderO'Mara這沒有任何意義。我想阻止取決於我的私人常量的人,這樣我可以在晚些時候輕鬆地更改它們,而不會讓用戶感到厭煩。 – PeeHaa
@halfer:還有更多這樣的問題 - 但是這個問題是要求我認爲不同的原因。 – hakre