2015-12-09 106 views
3

我想創建兩個Realm模型類和一個協議,兩個模型類都採用這兩個類。例如:我可以讓Realm Results類將協議用作泛型嗎?

​​

在這種情況下,我創建了兩個模型類和一個協議。

但是,當我轉移到執行,發生問題。下面的代碼寫在視圖控制器中:

此代碼沒有任何問題。但代碼如下:

var animals: Results<Animal>? { 
    switch currentSegmented { // this is from UISegmentedControl 
    case .Cat: // this is from enum 
     return self.cats 
    case .Dog: 
     return self.dogs 
} 

不編譯時出現錯誤:Results requires that Animal inherit from Object

但是,Animal是一個協議,因此不能從Object繼承。

這裏還有可能使用協議嗎?

+0

在這種情況下,更好的解決方案是子類對象本身並將其稱爲Animal。從這裏你可以繼承各自的動物。 – Shripada

+0

@Shripada我相信這些作品,但你爲什麼認爲這是一個「更好的解決方案」? – Blaszard

+0

不是更好,正確的解決方案。很明顯,這是Realm的要求,Result只能包含'Object的 – Shripada

回答

5

我不認爲有一個很好的解決方案。 Swift中用戶定義的泛型是不變的,所以即使Animal是一個類,也不能將Results<Dog>轉換爲Results<Animal>

的令人不快的詳細解決方案是創建一個明確的包裝類型在你的不同種結果:

enum AnimalResultsEnum { 
    case DogResults(dogs: Results<Dog>) 
    case CatResults(cats: Results<Cat>) 
} 

class AnimalResults { 
    var animals = AnimalResultsEnum.DogResults(dogs: try! Realm().objects(Dog)) 

    var realm: Realm? { 
     switch animals { 
     case .DogResults(let dogs): 
      return dogs.realm 
     case .CatResults(let cats): 
      return cats.realm 
     } 
    } 

    var count: Int { 
     switch animals { 
     case .DogResults(let dogs): 
      return dogs.count 
     case .CatResults(let cats): 
      return cats.count 
     } 
    } 

    subscript(index: Int) -> Animal { 
     switch animals { 
     case .DogResults(let dogs): 
      return dogs[index] 
     case .CatResults(let cats): 
      return cats[index] 
     } 
    } 

    // ... wrap the rest of the methods needed ... 
} 

您可以通過,而不是創建一個半型擦除容器包裝的結果使這個通用:

class CovariantResults<T: Object> { 
    private var base: _CovariantResultsBase<T> 

    init<U: Object>(_ inner: Results<U>) { 
     base = _CovariantResultsImpl<T, U>(inner) 
    } 

    subscript(index: Int) -> T { 
     return base[index] 
    } 

    // ... wrap the rest of the methods needed ... 
} 

class _CovariantResultsBase<T: Object> { 
    subscript(index: Int) -> T { fatalError("abstract") } 
    // ... wrap the rest of the methods needed ... 
} 

class _CovariantResultsImpl<T: Object, U: Object>: _CovariantResultsBase<T> { 
    private let impl: Results<U> 

    init(_ inner: Results<U>) { 
     impl = inner 
    } 

    override subscript(index: Int) -> T { 
     return impl[index] as! T 
    } 

    // ... wrap the rest of the methods needed ... 
} 

// Used as: 
let animals = CovariantResults<Animal>(try! Realm().objects(Dog)) 
+0

協變結果的最佳解決方案。謝謝!我改變了一件事:動物不能是U型。協議無法創建結果。否則根本沒有任何問題。所以我創建了我需要使用的所有類型的基類作爲從Object繼承並符合我的協議的通用結果。如創建AnimalProtocol並製作Animal:Object,AnimalProtocol類,然後使用Animal作爲所有其他基類。像魅力一樣工作! – Alexandr

相關問題