2017-02-17 220 views
0

看到奇怪的泛型行爲,這導致我相信我錯過了我理解中的某些東西。Swift:運行時泛型類型推斷

我正在使用以下方法循環拋出JSON響應並調用泛型方法。 UserCardEcard全部來自IDObject繼承,這反過來從Object(一類域)繼承

let props:[(label:String, type:IDObject.Type)] = [ 
    (label: "deletedUsers", type: User.self), 
    (label: "deletedCards", type: Card.self), 
    (label: "deletedECards", type: Ecard.self) 
] 

for prop in props { 
    if let ids = json[prop.label].arrayObject as? [Int], ids.count > 0 { 
     DataManager.shared.delete(prop.type, ids: ids) 
    } 
} 

func delete<T:IDObject>(_ type:T.Type, ids:[Int]) { 
    guard ids.count > 0 else { return } 
    if let objectsToDelete = objects(type, where: NSPredicate(format: "identifier IN %@", ids)) { 
     delete(objectsToDelete) 
    } 
} 

func delete<T:Object>(_ objects:Results<T>) { 
    guard objects.count > 0 else { return } 
    do { 
     let realm = try Realm() 
     try realm.write { 
      realm.delete(objects) 
     } 
    } catch { 
     print(error) 
    } 
} 

delete(_ type:T.Type, ids:[Int])功能不能推斷泛型類型這種方式。

但是,展開for prop in props循環按預期工作。

if let userIds = json["deletedUsers"].arrayObject as? [Int], userIds.count > 0 { 
    DataManager.shared.delete(User.self, ids: userIds) 
} 

不要只泛型在編譯的時候工作,或者是有沒有辦法在運行時動態處理呢?

+0

究竟你「的意思*了'刪除'函數不能通過這種方式推斷泛型*「?你得到一個編譯器錯誤? (如果是的話,在哪裏?)你錯過了'DataManager.shared.delete(prop.type,ids:ids')的右括號,除非你用單個參數重載'delete',否則不能調用它一個參數('delete(objectsToDelete)')。請你提供一個[mcve],包括預期的行爲和實際行爲? – Hamish

+0

@Hamish整個代碼庫非常大,我不能隨意分享它我已經在這裏大量地編輯了它,並且我已經修復了缺失的右括號,'delete'確實被重載了 - 'delete(:)'方法需要一個'Results '''IDObject'繼承自'Object'。我看到的行爲是在刪除(objects :)方法,objects.count == 0 – dmorrow

+0

你不需要共享整個代碼庫 - 只有一個最小的自包含的例子,重現相同的問題。是' DataManager.shared.delete'應該引用'delete(_:ids:)'?什麼是對象(_:where:)'return?(你沒有甚至必須顯示功能,只是模擬一個功能,重現相同的問題)。 「ids」甚至與問題有關嗎? (如果沒有,請將其刪除)。 – Hamish

回答

1

泛型在編譯時被評估並被分配一個具體的類型。沒有「運行時類型推斷」這樣的東西。

我想你想的主要變化是:

func delete(_ type:IDObject.Type, ids:[Int]) { 

你不想專注於type這個功能,你只是想通過type

不清楚objects(_:where:)返回什麼,所以這可能會破壞您的delete方法。您可能需要使它不那麼具體:

func delete(_ objects:Results<Object>) { 

(這是不是子類型的靈丹妙藥;我假設objects(_:where:)恰好返回Results<Object>

+0

我認爲通過「在運行時鍵入推論」他意味着類似[this](http://stackoverflow.com/a/30945263/5175709)閱讀**協議可以選擇靜態或動態調度。**他基本上是指靜態與動態調度。 – Honey

+0

我可能在這裏錯過了一些東西,但我沒有看到如何改變'type'參數的靜態類型將會改變OP代碼的運行時行爲(考慮到當他調用delete時(假設它實際上是DataManager.shared .delete'),'T'已被推斷爲'IDObject')。另請注意,泛型僅作爲編譯器優化專用。 – Hamish

+0

它可能已經被推斷爲'IDObject',但專業上它是最好的混亂,因爲讀者可能認爲更多的正在發生的事情(這是很難測試,因爲此代碼不能編譯)。 「專業化」並不一定意味着編譯器編寫了一個獨特的函數版本。 '陣列'是Array'的'專業化'上Int',不管它是如何由編譯器實現。 –