我想实现数字 struct ,它应该由整型文字初始化.

喜欢:

let digit: Digit = 5

但SWIFT不应该允许这样做(或者,作为一种 Select ,应该提出例外):

let digit: Digit = 15

我写了这段代码,但看起来不太好:

   struct Digit: ExpressibleByIntegerLiteral, Equatable, CustomStringConvertible {
    
    typealias IntegerLiteralType = Int
    
    var description: String {
        String(value)
    }
    
    var value: IntegerLiteralType {
        // Unfortunately, set throws can't be implemented, only get throws.
        willSet(newValue) {
            if 0...9 ~= value {
                self.value = newValue
            }
        }
    }


    init(integerLiteral: IntegerLiteralType) {
        if 0...9 ~= integerLiteral {
            value = integerLiteral
        } else {
            // This is definitely not good and may cause side effects.
            // But init for ExpressibleByIntegerLiteral can't be failable.
            value = 0
        }
    }
    
    init?(from char: Character?) {
        guard let char,
              let newValue = IntegerLiteralType(String(char)),
              0...9 ~= newValue
        else {
            return nil
        }
        value = newValue
    }
}

在SWIFT 5.8中,我如何克服这一点?我猜在下一个版本中可能会使用宏,但不幸的是,我的SWIFT版本仍然没有它们.

谢谢.

推荐答案

不可能对除0-9之外的所有数字产生编译器错误,您可以做的最好的事情是最大化会产生编译器错误的数字的范围,使用最小的IntegerLiteralType,对于其他数字使用fatalError.

struct Digit: ExpressibleByIntegerLiteral {
    let value: UInt8
    
    init(integerLiteral value: UInt8) {
        guard (0...9).contains(value) else {
            fatalError("Digit must be between 0 and 9!")
        }
        self.value = value
    }
}

因为我使用UInt8作为IntegerLiteralType,所以这样的代码不能编译:

let x: Digit = 1000

像这样的事情会有fatalError个:

let x: Digit = 10

由于只有10个有效值,因此您可以考虑使用enum作为替代.Enum大小写不能以数字开头,因此您需要前面的内容:

enum Digit: UInt8 {
    case _0
    case _1
    case _2
    case _3
    case _4
    case _5
    case _6
    case _7
    case _8
    case _9
}

Swift相关问答推荐

日期格式yyyyyy—MM—dd hh:mm:ss +0000到dd MMM,以swift格式表示""""

";async let和";async之间的差异让我们等待";

了解SWIFT中的任务行为

我正在try 通过代码设置节中页眉和页脚的高度,但它不起作用

SwiftData/PersistentModel.swft:540:致命错误:不支持的关系密钥路径ReferenceWritableKeyPath

找出touch 点的屏幕亮度

如何在设备(或常量)地址空间中创建缓冲区?

在Swift中如何将NSUrl转换为本地路径URL

协议元类型'SomeProtocol.Type'上无法使用静态成员'currency'

当变量首次用于其自己的初始化时,如何清除变量...在初始化之前使用错误?

如何在 swiftui 中设置给定字符串类型日期的日期倒计时?

如何在不提交到应用store 的情况下在本地运行我的应用

将数据附加到 Firebase 实时数据库后,NavigationLink 将我重定向到上一个视图

如何在 SwiftUI 中通过按钮点击一次为一个更改设置动画?

为什么 Swift Tuples 只能在元素个数小于等于 6 的情况下进行比较?

通用枚举菜单 SwiftUI

如何防止 UITableViewCell 移动(Swift 5)

Swift 2 或 3 中的 Google Analytics 问题

转换为 swift 3 后,视图控制器中出现奇怪的通用函数

Swift - 要求实现协议的类是某个类的子类