由於Ruby中沒有類型,Ruby程序員如何確保函數接收正確的參數?現在,我正在重複執行if object.kind_of
/instance_of
語句來檢查並隨處增加運行時錯誤,這很醜陋。必須有更好的方式來做到這一點。Ruby程序員如何進行類型檢查?
回答
Ruby當然是動態類型的。
因此,方法文件確定類型合同;類型信息從正式類型系統移到[方法文檔中的非正式類型說明]。我將「行爲像一個數組」這樣的概念和諸如「是一個字符串」等細節混爲一談。來電者只能期望與聲明的類型一起工作。
如果主叫方違反此合同,則可能發生任何事情。該方法不用擔心:它被錯誤地使用了。
在上述的光,我避免檢查用於特定類型和避免試圖創建與這種行爲重載。
單元測試可以幫助確保合同適用於預期數據。
@cjk雖然這是一個很好的範例,但它仍然沒有回答這個問題。我建議你接受薩瓦的回答。 – anthropomorphic 2013-06-24 06:43:40
我個人的方式,我不確定它是否是一種推薦的方式,一般是在發生錯誤時進行類型檢查並執行其他驗證。我把類型檢查例程放在一個救援塊中。這樣,當給出正確的參數時,我可以避免性能損失,但在發生錯誤時仍然會返回正確的錯誤消息。
def foo arg1, arg2, arg3
...
main_routine
...
rescue
## check for type and other validations
raise "Expecting an array: #{arg1.inspect}" unless arg1.kind_of?(Array)
raise "The first argument must be of length 2: #{arg1.inspect}" unless arg1.length == 2
raise "Expecting a string: #{arg2.inspect}" unless arg2.kind_of?(String)
raise "The second argument must not be empty" if arg2.empty?
...
raise "This is `foo''s bug. Something unexpected happened: #{$!.message}"
end
假設在main_routine
,可以使用該方法each
上arg1
假設arg1
是一個數組。如果事實證明這是其他問題,那麼each
未定義,那麼裸露的錯誤消息將類似method each not defined on ...
,從方法foo
的用戶角度來看,這可能沒有幫助。在這種情況下,原始錯誤消息將被消息Expecting an array: ...
替代,這更有幫助。
但是,這個問題是由於其他問題被拾取而導致*真實*錯誤可能被掩蓋。所以,雖然它也可能成爲一個問題,但它可能與實際提出的內容無關。如果要完成明確的類型檢查,首先*執行,而不是恢復。 – 2012-03-22 06:39:21
爲什麼使用'#{arg1}'而不是'#{arg1.inspect}'?或者更具體地說,''期待一個字符串:#{arg2}「'而不是'」期待一個字符串:#{arg2.inspect}「'? – 2012-03-22 22:48:07
@pst當我編輯時,可以通過在末尾加上另一個「raise」來避免。如果在'foo'內部引發錯誤,但所有驗證通過,則驗證檢查不夠或者'foo'內部存在錯誤。 – sawa 2013-03-09 13:03:54
如果一個方法有一個存在的理由,它將被調用。
如果編寫了合理的測試,一切都會被調用。
如果每個方法都被調用,那麼每個方法都將進行類型檢查。
不要浪費時間放入可能不必要地限制呼叫者的類型檢查,而只是重複運行時檢查。花時間寫作測試。
我建議在方法的使用開始加註到手動添加類型檢查,簡單而有效:
def foo(bar)
raise TypeError, "You called foo without the bar:String needed" unless bar.is_a? String
bar.upcase
end
最好的方法,當你沒有太多的參數,也是一個建議是使用關鍵字如果你有多個參數,並且注意其當前/將來的實現細節,那麼它們可以在ruby 2+上得到,他們正在改善這種情況,給程序員一種方法來看看值是否爲零。
加:您可以使用自定義異常
class NotStringError < TypeError
def message
"be creative, use metaprogramming ;)"
#...
raise NotStringError
可以使用Design by Contract方法,與contracts紅寶石的寶石。我覺得很好。
- 1. 如何避免對子類進行類型檢查?
- 2. 何時進行類型參數的類型檢查?
- 3. Ruby類如何檢測運行它的進程名稱?
- 4. 對Caché對象進行類型檢查
- 5. 使用VBA進行類型檢查
- 6. 在程序員的記事本中進行拼寫檢查
- 7. 如何啓用需要在命令行上進行類型檢查的規則的類型檢查?
- 8. 如何在運行時檢查類型?
- 9. 使用枚舉進行類型檢查 - 如何正確範圍
- 10. 如何在MongoDB中進行類型檢查?
- 11. Python與Java相比如何進行類型檢查?
- 12. 如何使用後臺工作人員檢查進程進度
- 13. 打字稿類型檢查 - Backbone.Model實例無法進行類型檢查
- 14. 爲什麼在GHC 7.10中進行類型檢查的代碼不再在GHC 8.0.1中進行類型檢查?
- 15. 如何檢查值類型?
- 16. 如何檢查NSDATA類型?
- 17. 如何檢查類型?
- 18. 如何檢查進程的進程
- 19. 將程序集加載到另一個AppDomain中並進行類型檢查
- 20. 如何檢查rethinkdb進程
- 21. Parallel.ForEach如何檢查進程?
- 22. 如何檢查inno安裝程序中的分區類型?
- 23. 如何查詢正在運行的進程的登錄類型?
- 24. 如何檢查ruby中的類屬性?
- 25. 如何查找檢查特定類類型的行數?
- 26. 如何檢查正在運行的java程序的進度
- 27. 如何檢查Java類成員訂單
- 28. 如何動態檢查演員的類型
- 29. 如何檢查會員運營商(類型)?
- 30. 如何檢查ruby進程的性能問題?
爲什麼你需要確保輸入是特定類型的?函數做他們被告知的事情,不應該被迫輸入檢查。 – Blender 2012-03-22 05:23:50
查閱「鴨子打字」 – 2012-03-22 05:24:30
@Blender例如。 setNextNode(link)。在這個函數中,如果我沒有類型檢查任何東西都可以傳入......我現在正在做一個任務,並且我被告知要進行類型檢查並確保運行時安全。 – kun 2012-03-22 05:35:31