首页 > 解决方案 > 具有特定 Self 类型的 Swift 协议扩展

问题描述

我为 UnsignedInteger 协议添加了一个扩展,以添加一个以十六进制格式表示数字的十六进制方法。我还希望特定的符合结构具有参数的默认值。我写的是下面的。

extension UnsignedInteger {
    func hex(withFieldWidth fieldWidth: Int, andUseUppercase uppercase: Bool = true) -> String {
        return String(format: "%0\(fieldWidth)\(uppercase ? "X" : "x")", self as! CVarArg)
    }
}

extension UnsignedInteger where Self == UInt8 {
    func hex(withFieldWidth fieldWidth: Int = 2, andUseUppercase uppercase: Bool = true) -> String {
        // should call the UnsignedInteger implementation with the default parameters
        return hex(withFieldWidth: fieldWidth, andUseUppercase: uppercase)
    }
}

extension UnsignedInteger where Self == UInt16 {
    func hex(withFieldWidth fieldWidth: Int = 4, andUseUppercase uppercase: Bool = true) -> String {
        // should call the UnsignedInteger implementation with the default parameters
        return hex(withFieldWidth: fieldWidth, andUseUppercase: uppercase)
    }
}

但是,对于 UInt8 和 UInt16 特定的扩展,它似乎是在调用自身而不是第一个扩展块中的十六进制,正如我收到的 UInt8 和 UInt16 块的警告消息所解释的那样All paths through this function will call itself

如果我fieldWidh从 UInt8 和 UInt16 块中删除 ,调用十六进制(带有硬编码值fieldWidth)似乎编译得很好,我相信这样它是从第一个扩展块调用十六进制方法。下面是编译良好的代码。

extension UnsignedInteger {
    func hex(withFieldWidth fieldWidth: Int, andUseUppercase uppercase: Bool = true) -> String {
        return String(format: "%0\(fieldWidth)\(uppercase ? "X" : "x")", self as! CVarArg)
    }
}

extension UnsignedInteger where Self == UInt8 {
    func hex(andUseUppercase uppercase: Bool = true) -> String {
        // should call the UnsignedInteger implementation with the default parameters
        return hex(withFieldWidth: 2, andUseUppercase: uppercase)
    }
}

extension UnsignedInteger where Self == UInt16 {
    func hex(andUseUppercase uppercase: Bool = true) -> String {
        // should call the UnsignedInteger implementation with the default parameters
        return hex(withFieldWidth: 4, andUseUppercase: uppercase)
    }
}

在进行协议扩展时,有没有办法为特定的符合结构的参数指定默认值?

标签: swiftprotocolsprotocol-extension

解决方案


在进行协议扩展时,有没有办法为特定的符合结构的参数指定默认值?

您已经在问题中强调了这种方法的问题。


我怎样才能以不同的方式解决它?

UnsignedInteger从那里继承BinaryInteger可以为您提供bitWidth信息(UInt8=> 8UInt16=>16等等)。

extension UnsignedInteger {
    func hex(uppercase: Bool = true) -> String {
        let fieldWidth = self.bitWidth / 4
        return String(format: "%0\(fieldWidth)\(uppercase ? "X" : "x")", self as! CVarArg)
    }
}

以上使其适用于UInt, UInt8, UInt16, UInt32& UInt64


更进一步,您可以使用FixedWidthInteger& 现在它适用于所有有符号和无符号整数。 在此处输入图像描述


推荐阅读