【问题标题】:How to convert Swift "switch case is ..." block into loop oriented code?如何将Swift“switch case is ...”块转换为面向循环的代码?
【发布时间】:2015-12-01 01:04:15
【问题描述】:

我的代码如下所示:

class Base {
    func launch(code1: Int, code2: Int) -> Bool { return false }
}

class A: Base {}
class B: Base {}
class C: Base {}

func trynext(obj: Base) -> Base? {
    switch obj {
    case is A: return B()
    case is B: return C()
    default: return nil
    }
}

基本上,我有很多(比如 20 个)公共基类的子类,我需要一一浏览它们。这些子类代表解析器,我正在一个接一个地尝试它们以发现哪个解析器正确解析了一些数据。

如果解析失败,我会调用函数trynext 来返回“下一个解析器”来尝试。你可以想象,如果构造函数带参数(所有子类都带相同参数),并且子类越多等等,这个switch 语句就会变得难以接受。

有什么方法可以通过将类放入某种数组并以某种方式循环遍历它来简化此代码?这个想法是减少样板文件,以便我最终使用像 [A, B, C] 这样的结构,这意味着要尝试的子类和尝试它们的顺序。

【问题讨论】:

    标签: swift class switch-statement


    【解决方案1】:

    我会使用一个协议(比如:“解析器”)来定义一个描述解析器可以做什么的接口。例如:解析(数据);

    此协议的不同实现(A、B、C……)将有自己的代码来处理解析。

    解析控制器(或管理器或您想出的任何名称)将存储Parser 对象的数组。

    在一个forEach循环中,你可以调用每个try Parser.parse(data); …如果解析正常,则处理进入下一个或中止。

    解析器的特定实现(A、B、C……)与调用者无关(应该如此)。 ParsingController(你现在有你的开关),不会关心会发生什么。它只对成功或失败感兴趣,分别停止或尝试下一个(如果有下一个)。

    更新:我创建了一个小的 Playground 代码,您可以粘贴并了解我的意思。

    UPDATE2:我添加了一个扩展协议,因此您可以了解如何使用类似于 abstract 类的东西来拥有一组基本/通用的函数/值。

    import Swift
    
    protocol Parser {
        func parse(code1: Int, code2: Int) -> Bool
    }
    
    extension Parser {
        var someCalculatedProperty: Int {
            return 12345
        }
        func someCommonMethod() {
            print("Some Common Method")
        }
    }
    
    class A : Parser {
        func parse(code1: Int, code2: Int) -> Bool { return false }
    }
    class B : Parser {
        func parse(code1: Int, code2: Int) -> Bool { return false }
    }
    class C : Parser {
        func parse(code1: Int, code2: Int) -> Bool { return true }
    }
    
    // Create 4 Parsers (two of the same type, just to demonstrate)
    var parsers = [Parser](arrayLiteral: A(), A(), B(), C())
    
    // Iterate the parsers until we get a success
    for parser in parsers {
        if parser.parse(0, code2: 1) {
            print("Success")
            // Just for fun, call common parser methods.
            parser.someCommonMethod()
            print(parser.someCalculatedProperty)
            break
        } else {
            print("Fail")
        }
    }
    

    输出应该是:

    Fail
    Fail
    Fail
    Success
    Some Common Method
    12345
    

    3 个失败(因为 A、A、B 返回 false)和 Success 因为 C 返回 true。然后是常用方法的输出。

    【讨论】:

    • 谢谢马丁,但我实际上是在尝试创建一个类数组,因为每个类可能有多个实例。有可能吗?
    • 有一个类数组,我只是替换了你的继承来使用协议(我输入的行://创建“3”解析器)这创建了 3 个不同类的三个实例(a b 和c) 每个类可以有任意数量的实例。 (还有一个原因为什么你有同一个解析器的多个实例?你不能只为同一个实例提供不同的数据吗?)我没有这样做,但你的解析器可能有一个共同的祖先/基类(A B 和如果您想共享代码,C 可以全部从 Base 继承),但无论如何我都会使用协议。
    • 查看更新后的代码。也许我不明白你的想法?
    猜你喜欢
    • 1970-01-01
    • 2021-10-22
    • 2021-01-09
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 2023-01-22
    • 2015-07-01
    • 1970-01-01
    相关资源
    最近更新 更多