- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
情况
我有两个通用类,它们将从 api 和数据库中获取数据,分别是 APIDataSource 和 DBDataSource
我将在创建 View 模型时将两个类中的任何一个注入(inject) View 模型, View 模型将使用该类来获取所需的数据。我希望 View 模型在两个类中的工作完全相同。所以我不希望类有不同的通用约束
//sudo 代码
ViewModel(APIDataSource
//我想在以后更改数据源
ViewModel(DBDataSource
要从 API 获取数据,ResponseModel 需要确认“可解码”,因为我想从 JSON 创建该对象。要从领域数据库中获取数据,它需要继承自 Object
在 ViewModel 内部,我希望得到类似的响应
//sudo 代码
self.dataSource.request("param1", "param2")
如果开发人员尝试从数据库获取 api 数据,反之亦然,它将检查类型是否正确并抛出正确的错误。
Playground 代码的剥离版本
以下是代码的剥离版本,它显示了我想要实现的目标或我被卡住的地方(将不受约束的泛型类型转换为确认可解码的泛型类型)
import Foundation
// Just to test functions below
class DummyModel: Decodable {
}
// Stripped out version of function which will convert json to object of type T
func decode<T:Decodable>(_ type: T.Type){
print(type)
}
// This doesn't give compilation error
// Ignore the inp
func testDecode<T:Decodable> (_ inp: T) {
decode(T.self)
}
// This gives compilation error
// Ignore the inp
func testDecode2<T>(_ inp: T){
if(T.self is Decodable){
// ??????????
// How can we cast T at runtime after checking T confirms to Decodable??
decode(T.self as! Decodable.Type)
}
}
testDecode(DummyModel())
任何帮助或解释这无法工作将不胜感激。提前致谢:)
最佳答案
正如@matt 所建议的,将我的各种评论以“您的问题没有好的解决方案,您需要重新设计您的问题”的形式转移到一个答案上。
您尝试做的事情往好里说是脆弱的,往坏里说是不可能的。当您尝试提高性能时,Matt 的方法是一个很好的解决方案,但如果它影响行为,它就会以令人惊讶的方式崩溃。例如:
protocol P {}
func doSomething<T>(x: T) -> String {
if x is P {
return "\(x) simple, but it's really P"
}
return "\(x) simple"
}
func doSomething<T: P>(x: T) -> String {
return "\(x) is P"
}
struct S: P {}
doSomething(x: S()) // S() is P
所以这就像我们期望的那样工作。但是我们可能会以这种方式丢失类型信息:
func wrapper<T>(x: T) -> String {
return doSomething(x: x)
}
wrapper(x: S()) // S() simple, but it's really P!
所以你不能用泛型来解决这个问题。
回到你的方法,它至少有可能是稳健的,但它仍然行不通。 Swift 的类型系统无法表达你想表达的意思。但我认为无论如何你都不应该尝试这么说。
In the method that fetch data I will check type of generic type and if it confirms to "Decodable" protocol I will use it to fetch data from api else from database.
如果从 API 获取与从数据库获取代表不同的语义(而不仅仅是性能改进),即使您可以让它工作,这也是非常危险的。程序的任何部分都可以将 Decodable
附加到任何类型。它甚至可以在单独的模块中完成。添加协议(protocol)一致性不应改变程序的语义(外部可见行为),而只能改变性能或功能。
I have a generic class which will fetch data either from api or database
完美。如果您已经有一个类,类继承在这里很有意义。我可能会像这样构建它:
class Model {
required init(identifier: String) {}
}
class DatabaseModel {
required init(fromDatabaseWithIdentifier: String) {}
convenience init(identifier: String) { self.init(fromDatabaseWithIdentifier: identifier )}
}
class APIModel {
required init(fromAPIWithIdentifier: String) {}
convenience init(identifier: String) { self.init(fromAPIWithIdentifier: identifier )}
}
class SomeModel: DatabaseModel {
required init(fromDatabaseWithIdentifier identifier: String) {
super.init(fromDatabaseWithIdentifier: identifier)
}
}
根据您的具体需要,您可以重新安排它(这里也可以使用协议(protocol))。但关键是 model 知道如何获取自己。这使得在类中使用 Decodable 变得很容易(因为它可以很容易地使用 type(of: self)
作为参数)。
您的需求可能有所不同,如果您更好地描述它们,也许我们会找到更好的解决方案。但它不应该基于某些东西是否仅仅符合协议(protocol)。在大多数情况下,这是不可能的,即使你让它工作,它也会很脆弱。
关于Swift:将不受约束的泛型类型转换为确认可解码的泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51877722/
考虑一个相关矩阵 r,表示变量 1 到 10 之间的相关性: r thr)) NA else sum(score[x]) }) min(summed_score, na.rm=T) ## [1] 1
我在 firebase 中有一个值需要增加,它受竞争条件的影响,所以我更愿意一次完成所有这些。 node: { clicks: 3 } 我需要设置 clicks = cli
我是一名优秀的程序员,十分优秀!