swift - 在运行时确定协议(protocol)类型

标签 swift

我们如何根据用户提供的实例确定协议(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/

相关文章:

ios - 在 swift 3 中上传到 Firebase 存储之前调整 UIImage 的大小

text - 将墓碑类型雕刻成立方体(Swift - SceneKit)

ios - 函数返回是什么意思?

ios - ExpandableLable 仅适用于系统字体

swift - 如何存储使用委托(delegate)方法发回的数据?

ios - 从 Firebase 中检索一定数量的 child

swift - ARKit – 获取场景中 ARCamera 的当前位置

ios - 在 Swift 3.0/ObjectiveC 中的现有 XML 字符串中添加 CDATA 部分

swift - Collection View 插入项目奇怪的动画

swift - 使用 Swift 选择 UITextView 的整个文本