我们如何根据用户提供的实例确定协议(protocol)是否符合特定的子类型,如果无法通过这种方式确定任何替代解决方案。
API
protocol Super {}
protocol Sub: Super {} //inherited by Super protocol
class Type1: Super {} //conforms to super protocol
class Type2: Type1, Sub {} //conforms to sub protocol
在另一个 API 类中
func store(closures: [() -> Super]) {
self.closures = closures
}
什么时候打电话
func go() {
for closure in closures {
var instance = closure()
if instance is Super {
//do something - system will behave differently
} else { //it's Sub
//do something else - system will behave differently
}
}
}
api 的用户
class Imp1: Type1 {}
class Imp2: Type2 {}
var closures: [() -> Super] = [ { Imp1() }, { Imp2() } ]
store(closures)
我目前在 API 中的解决方法
func go() {
for closure in closures {
var instance = closure()
var behavior = 0
if instance as? Type2 != nil { //not so cool, should be through protocols
behavior = 1 //instead of implementations
}
if behavior == 0 { //do something within the api,
} else { //do something else within the api
}
//instance overriden method will be called
//but not important here to show, polymorphism works in here
//more concerned how the api can do something different based on the types
}
}
最佳答案
您正在跳过很多环节来手动重新创建动态调度,即协议(protocol)和类的目的之一。尝试实际使用真正的运行时多态性来解决您的问题。
拿这段代码:
if instance is Super {
//do something
} else { //it's Sub
//do something else
}
你的意思是,如果它是父类(super class),运行父类(super class)方法,否则,运行子类。这有点颠倒——通常当你是一个子类时,你希望运行子类代码而不是相反。但假设您将其转换为更传统的顺序,您实际上是在描述调用协议(protocol)的方法并期望调用适当的实现:
(闭包与手头的问题并没有真正相关,所以暂时忽略它们)
protocol Super { func doThing() }
protocol Sub: Super { } // super is actually a bit redundant here
class Type1: Super {
func doThing() {
println("I did a super thing!")
}
}
class Type2: Sub {
func doThing() {
println("I did a sub thing!")
}
}
func doSomething(s: Super) {
s.doThing()
}
let c: [Super] = [Type1(), Type2()]
for t in c {
doSomething(t)
}
// prints “I did a super thing!”, then “I did a sub thing!"
要考虑的备选方案:消除 Sub
,并让 Type2
继承自 Type1
。或者,由于此处没有类继承,您可以使用结构而不是类。
关于swift - 在运行时确定协议(protocol)类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27753405/