【问题标题】:关联枚举的通用类型
【发布时间】:2022-01-23 13:22:13
【问题描述】:

我有一个enum,如下所示:

public enum MyErrorEnum: LocalizedError {
    case FileNotFound(String = "Failed to find file.", file: String)

    public var errorDescription: String? {
        if let current = Mirror(reflecting: self).children.first {
            let mirror = Mirror(reflecting: current.value);
            // Initial error description.
            let message = mirror.children.first?.value as? String
                ?? current.label ?? "Unknown-case";
            var context = "";
            // Iterate additional context.
            var i = 0;
            for associated in mirror.children {
                if i >= 1 {
                    if let text = associated.value as? String {
                        context += "\n  ";
                        if let label: String = associated.label {
                            context += "\(label): "
                        }
                        context += text;
                    }
                }
                i += 1;
            }
            return context.isEmpty ? message : (
                message + " {" + context + "\n}"
            );
        }
        return "\(self)";
    }
}

用法:

do {
    let path = "/path/to/file.txt";
    throw MyErrorEnum.FileNotFound(
        file: path
    );
} catch {
    print(error.localizedDescription);
}

输出:

Failed to find file. {
  file: /path/to/file.txt
}

现在我想在任何实现LocalizedErrorenum 中重用errorDescription,只需将errorDescription 的逻辑移动到扩展中即可。

我应该如何改变下面的工作扩展(就上述而言)?

public enum MyErrorEnum: LocalizedError {
    case FileNotFound(String = "Failed to find file.", file: String)
}

extension DONT_KNOW_WHAT_GOES_HERE where Self: LocalizedError {
    public var errorDescription: String? {
        // ... imagine all above logic moved here.
    }
}

【问题讨论】:

  • @Sweeper 会影响实现LocalizedError 的所有内容,例如,我想要extension RawRepresentable where RawValue == String, Self: LocalizedError {} 之类的东西但对于关联枚举

标签: swift enums


【解决方案1】:

正如 cmets 中所建议的,Swift 似乎还没有为关联枚举提供 Generic-Type(虽然它为 Raw-Value 枚举提供了 RawRepresentable)。

解决方案;为了不影响实现LocalizedError 的所有内容,请创建您自己的协议,例如:

public protocol LocalizedErrorEnum: LocalizedError {
    var errorDescription: String? { get }
}

extension LocalizedErrorEnum {
    public var errorDescription: String? {
        if let current = Mirror(reflecting: self).children.first {
            let mirror = Mirror(reflecting: current.value);
            // Initial error description.
            let message = mirror.children.first?.value as? String
                ?? current.label ?? "Unknown-case";
            var context = "";
            // Iterate additional context.
            var i = 0;
            for associated in mirror.children {
                if i >= 1 {
                    if let text = associated.value as? String {
                        context += "\n  ";
                        if let label: String = associated.label {
                            context += "\(label): "
                        }
                        context += text;
                    }
                }
                i += 1;
            }
            return context.isEmpty ? message : (
                message + " {" + context + "\n}"
            );
        }
        return "\(self)";
    }
}

用法:

public enum MyErrorEnum: LocalizedErrorEnum {
    case FileNotFound(String = "Failed to find file.", file: String)
}

【讨论】:

  • 仅供参考,不需要分号,甚至不鼓励使用分号。
  • @JoakimDanielson 我不知道 不鼓励,但在 JavaScript 中也不需要分号,但在 鼓励 JS 防止错误(想法是,将编译和/或丑化留给各自的工具,无需手动删除分号)。
  • @JoakimDanielson 但即使在 Swift 中,如果有人错误地将 .doSomething() 而不是 doSomething() 添加到下一行,如果我们没有分号,它只需要一个点即可巨大的差异(我更喜欢多按一个按钮,而不是整天调试)。
  • @JoakimDanielson 我希望能解释一下,如果Swift 不喜欢分号,他们应该完全阻止在下一行继续(而不是像JavaScript 那样将分号设为可选) )。
  • @JoakimDanielson 当然也可能有其他问题;但是有多个同名的方法很常见,所以我们希望它们会导致错误。但是,另一个原因是我想通过查看而不是思考和阅读整个内容来立即找到语句结束。
猜你喜欢
  • 2018-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-14
  • 1970-01-01
  • 2021-11-01
  • 1970-01-01
  • 2019-08-05
相关资源
最近更新 更多