当前位置:  开发笔记 > 编程语言 > 正文

我可以使Realm Results类使用协议作为泛型吗?

如何解决《我可以使RealmResults类使用协议作为泛型吗?》经验,为你挑选了1个好方法。

我想创建两个Realm模型类和一个协议,它由两个模型类采用.例如:

class Dog: Object, Animal {
    dynamic var name = ""
}
class Cat: Object, Animal {
    dynamic var name = ""
}
protocol Animal {
    var name: String { get }
}

在这种情况下,我创建了两个模型类和一个协议.

但是,当我转移到实现时,问题就出现了.下面的代码是在视图控制器中编写的:

var dogs: Results? {
    return try! Realm().objects(Dog)
}
var cats: Results {
    return try! Realm().objects(Cat)
}

这段代码没有任何问题.但是下面的代码:

var animals: Results? {
    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.

这里仍然可以使用协议吗?



1> Thomas Goyne..:

我不认为有一个很好的解决方案.在斯威夫特用户定义泛型是不变的,所以即使Animal是你不能将一个类ResultsResults.

令人不快的详细解决方案是围绕不同类型的结果创建一个显式的包装器类型:

enum AnimalResultsEnum {
    case DogResults(dogs: Results)
    case CatResults(cats: Results)
}

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 {
    private var base: _CovariantResultsBase

    init(_ inner: Results) {
        base = _CovariantResultsImpl(inner)
    }

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

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

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

class _CovariantResultsImpl: _CovariantResultsBase {
    private let impl: Results

    init(_ inner: Results) {
        impl = inner
    }

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

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

// Used as:
let animals = CovariantResults(try! Realm().objects(Dog))

推荐阅读
有风吹过best
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有