【问题标题】:Swift generics extension to multiple classesSwift 泛型扩展到多个类
【发布时间】:2017-11-21 07:36:54
【问题描述】:

所以我想为 NSNumber、Int、Double 和 Float 添加一个通用扩展,其中的值被转换为格式化的字符串。

我首先创建了一个自定义协议:

protocol MyFormatConvertible {
    var toMyFormat: String { get }
}
extension NSNumber: MyFormatConvertible {}
extension Double: MyFormatConvertible {}
extension Float: MyFormatConvertible {}
extension Int: MyFormatConvertible {}

现在我正在尝试将格式添加到扩展中:

extension MyFormatConvertible {
    public var toMyFormat: String {
        let numberValue = NSNumber(value:self)
    ....

但这似乎不起作用,因为我收到了错误:

无法使用参数列表为“NSNumber”类型调用初始化程序 输入“(值:自我)”

关于如何解决这个问题的任何提示?

【问题讨论】:

    标签: swift generics protocols protocol-extension


    【解决方案1】:

    NSNumber(value:) 有几个重载,用于各种 number 类型,但没有通用的NSNumber(value:) 构造函数。

    一种可能的解决方法是使用

    func string(for obj: Any?) -> String?
    

    NumberFormatter 的“抽象”超类 Formatter 的函数,它接受任何类型的参数(但可能返回 nil):

    protocol MyFormatConvertible {
        var toMyFormat: String { get }
    }
    
    extension MyFormatConvertible {
        var toMyFormat: String {
            let formatter = NumberFormatter()
            formatter.numberStyle = .spellOut // <-- Just for demonstration purposes!!
            return formatter.string(for: self) ?? "\(self)"
        }
    }
    
    extension NSNumber: MyFormatConvertible {}
    extension Double: MyFormatConvertible {}
    extension Float: MyFormatConvertible {}
    extension Int: MyFormatConvertible {}
    
    print(123.toMyFormat) // one hundred twenty-three
    print(Float.pi.toMyFormat) // three point one four one five nine two five zero two five nine three nine nine
    

    【讨论】:

    • 我实际上想在该函数中使用 Numberformatter(我想将数字格式化为带有货币符号的货币)。
    • @Lefteris:那个函数里面有一个NumberFormatter,你可以根据自己的需要配置。 numberStyle = .spellOut 只是一个示例,将其替换为 numberStyle = .currency
    • Martin,这似乎适用于 NSNumberDoubleInt,但不适用于 Float。我收到编译器错误:Type 'Float' does not conform to protocol 'MyFormatConvertible'
    • @Lefteris:你加了extension Float: MyFormatConvertible {}吗? – 上面的代码是我(工作)测试程序的精确副本。
    • 马丁我有。出于某种原因,在清理项目后它确实编译了。没有意义,但它正在工作。谢谢你解决了我的问题
    【解决方案2】:

    您可以简单地使用String(describing: self) 来实现这一点。

    protocol MyFormatConvertible {
        var toMyFormat: String { get }
    }
    
    extension MyFormatConvertible {
    
        var toMyFormat: String {
          return String(describing: self)
       }
    }
    
    extension NSNumber: MyFormatConvertible {}
    extension Double: MyFormatConvertible {}
    extension Float: MyFormatConvertible {}
    extension Int: MyFormatConvertible {}
    
    print(1.toMyFormat)
    print(1.2.toMyFormat)
    print(1.234.toMyFormat)
    print(NSNumber(value: 1.23456).toMyFormat)
    

    【讨论】:

    • 这很整洁。但是,这与仅以功能方式调用 String(describing: ) 基本相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多