Ios 我可以让realmresults类将协议用作泛型吗?
我想创建两个领域模型类和一个协议,这是由两个模型类采用的。例如:Ios 我可以让realmresults类将协议用作泛型吗?,ios,swift,protocols,realm,Ios,Swift,Protocols,Realm,我想创建两个领域模型类和一个协议,这是由两个模型类采用的。例如: class Dog: Object, Animal { dynamic var name = "" } class Cat: Object, Animal { dynamic var name = "" } protocol Animal { var name: String { get } } 在本例中,我创建了两个模型类和一个协议 然而,当我转到实现时,问题出现了。以下代码是在view control
class Dog: Object, Animal {
dynamic var name = ""
}
class Cat: Object, Animal {
dynamic var name = ""
}
protocol Animal {
var name: String { get }
}
在本例中,我创建了两个模型类和一个协议
然而,当我转到实现时,问题出现了。以下代码是在view controller中编写的:
var dogs: Results<Dog>? {
return try! Realm().objects(Dog)
}
var cats: Results<Cat> {
return try! Realm().objects(Cat)
}
var狗:结果如何?{
返回try!Realm().objects(Dog)
}
风险评估:结果{
返回try!Realm().objects(Cat)
}
这段代码没有任何问题。但代码如下:
var animals: Results<Animal>? {
switch currentSegmented { // this is from UISegmentedControl
case .Cat: // this is from enum
return self.cats
case .Dog:
return self.dogs
}
var动物:结果?{
开关currentSegmented{//这是来自UISegmentedControl
case.Cat://这是来自enum的
回归自我
案例.狗:
回归自我
}
未编译,错误为:结果要求动物从对象继承
但是,Animal
是一个协议,因此不能从对象继承
仍然可以在这里使用协议吗?我认为没有一个好的解决方案。Swift中的用户定义泛型是不变的,因此即使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 ...
}
enum animalresultsum{
案例犬结果(犬类:结果)
病例CatResults(cats:结果)
}
类动物结果{
var-animalresultsum.DogResults(狗:try!Realm().objects(狗))
var领域:领域{
交换动物{
案例。狗的结果(让狗):
返回狗王国
案例。CatResults(let-cats):
返回猫咪王国
}
}
变量计数:Int{
交换动物{
案例。狗的结果(让狗):
返回狗。计数
案例。CatResults(let-cats):
返回猫。计数
}
}
下标(索引:Int)->动物{
交换动物{
案例。狗的结果(让狗):
返回狗只〔索引〕
案例。CatResults(let-cats):
回归猫[索引]
}
}
//…包装所需的其余方法。。。
}
您可以通过创建一个半类型的已擦除容器来包装结果,从而使其成为泛型:
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))
类协变结果{
私有var基:\ u协方差结果基
初始化(内部:结果){
基本=_协方差结果简单(内部)
}
下标(索引:Int)->T{
返回基数[索引]
}
//…包装所需的其余方法。。。
}
类_协方差结果基{
下标(索引:Int)->T{fatalError(“abstract”)}
//…包装所需的其余方法。。。
}
类_convariatresultsiml:_convariatresultsbase{
私有let impl:结果
初始化(内部:结果){
impl=内部
}
覆盖下标(索引:Int)->T{
将impl[index]返回为!T
}
//…包装所需的其余方法。。。
}
//用作:
让动物=协变结果(try!Realm().objects(Dog))
在这种情况下,更好的解决方案是将对象本身子类化,并将其称为动物。从中,您可以将相应的动物子类化。@Shripada我相信这是可行的,但为什么您认为这是一个“更好的解决方案”?不是更好,是正确的解决方案。很明显,这是领域的要求,结果只能包含“Object”sAn Animal子类不会有帮助。Swift泛型是不变的,所以你不能将结果
转换为结果
。我认为如果没有总包装类型,这目前是不可能的。@ThomasGoyne啊,你是对的;我不是我把它烘干了,但它不起作用。我不知道你说的“粗包装类型”是什么意思,尽管如此。协变结果的伟大解决方案。谢谢!但我改变了一件事:动物不能是U型。结果不能用协议创建。否则就不会有任何问题。所以我为所有类型创建了基类,我需要用作从对象继承的通用结果,并符合我的协议。像create使用AnimalProtocol并制作类动物:对象,AnimalProtocol,然后使用Animal作为所有其他类的基类。效果非常好!