Swift中自定義類==比較方法未被呼叫的分析和解決
在專案中自定義了2個類:A和B,其中A含有B的例項變數.
在這2個類中都定義了==比較方法,按照正常來說:比較A,必然比較B.因為需要比較A中型別為B的例項變數.
但實際執行中發現,兩個字面上完全一樣的A例項物件,比較竟然不相等!!!
在A的==方法中下斷點,發現3個問題:
- 比較不相等是因為其中B例項變數的比較不相等
- B例項比較並沒有呼叫B中的==比較方法
- 最為奇怪的是:在Xcode的lldb中手動輸入同樣的相等表示式,結果卻是相等的!
首先將A和B中的==的方法比較一下,並沒有什麼值得特別注意的地方.
但是有一點,A在專案本身中,而B卻在static lib中!!!
在B中的==方法是這樣寫的:
static func ==(lhs: HyDateRange, rhs: HyDateRange) -> Bool {
if lhs.start == rhs.start,lhs.end == rhs.end{
return true
}
return false
}
其中start和end都是Date型別.看出什麼問題了麼???
我可以負責任地說:就該方法實現本身來說,是沒有任何問題的!只是該方法可見域錯了!它必須要是public!!!
如果不是public,則不會被外界(App)呼叫!但在比較的時候的確呼叫了一個返回false的比較方法,那是什麼呢?我們再來看一下類B的定義:
@objc(Objc_B)
public class B:NSObject,NSCopying,NSCoding{
}
可以看到,B派生自NSObject類,而NSObject類是遵守Equatable協議的,這意味著該類為你隱式生成了一個==方法,而你之前呼叫的就是這個方法,可想而知該方法預設比較的是兩個例項的===(引用)比較,自然返回false!
那麼A的==方法為什麼不用寫public限定?因為前面說了A是在專案裡的,在同一專案中統統都可以訪問到,所以不用寫public字首.
所以前兩個問題的解決很簡單,就是在B類的==方法前面加上public限定!
現在還有第三個問題:為毛除錯裡相同相等判斷表示式的結果和App實際執行時的不一樣???
這個本貓只有猜測:App執行時其==方法是編譯時繫結(至少對於類的這個static方法來說是),而lldb除錯時是即時繫結,此時lldb在執行時可以"看到"原本不能"看到"的非public==方法,所以判斷結果是正確的.
以上純屬猜測,歡迎指正 ?
最後,感謝觀賞 ?