如何创建一个可以保存像 UInt 这样的值但还有附加值 00 的类型?

Paw*_*ela 0 swift

我在尝试创建可以保存一组特定值的类型时遇到问题。这是一个篮球应用程序。

篮球运动员有球衣号码。在某些欧洲国家/地区(此应用程序就是这种情况),数字范围从 0 到 99(含)。但是还有一个附加值 00 可用,它与 0 不同。

我可以为此使用 String,但是 String 可以存储其他值,我必须编写额外的验证代码。

现在我使用 UInt 来存储数字。

有没有更好的方法将这些值存储为 Swift 类型?

Rob*_*ier 5

这是自定义类型的绝佳用例。它绝对不是 UInt 或任何类型的整数。是#23 + #24 = #47?那是胡说八道。#99 * #2 是什么?再说废话。这不是整数。

为了更进一步,虽然“00”是合法的泽西号码,但“01”不是。这不仅与“1”相同。这不是一个有效的数字。事实上,如果这是 NCAA,大多数数字都是不合法的(参见第 5 节第 5.b.2 条)。

相反, JerseyNumber 是它自己的类型。它有自己的合法操作(从技术上讲,它有自己的代数)。

用于 JerseyNumber 的最明智的原始类型是 String,因为您希望能够区分 00 和 0。我可能会以这种方式实现它,这将为您提供 Equatable、Hashable、CustomStringConvertible 和更方便的 Codable:

struct JerseyNumber: Hashable {
    private var string: String

    static let legalNumbers = ["0", "1", "2", "3", "4", "5", "00", "10", "11", "12", "13", "14", "15", "20", "21", "22", "23", "24", "25", "30", "31", "32", "33", "34", "35", "40", "41", "42", "43", "44", "45", "50", "51", "52", "53", "54", "55"]

    init?(_ string: String) {
        guard JerseyNumber.legalNumbers.contains(string) else { return nil }
        self.string = string
    }
}

extension JerseyNumber: CustomStringConvertible {
    var description: String { string }
}

extension JerseyNumber: Codable {
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let value = try container.decode(String.self)
        guard let number = JerseyNumber(value) else {
            throw DecodingError.dataCorruptedError(in: container,
                                                   debugDescription: "Could not decode JerseyNumber: \(value)")
        }
        self = number
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(string)
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,如果这不是 NCAA,或者如果您想要为您的号码制定其他规则,您可以重新init执行以执行或不执行任何对您的问题有意义的方式。例如,您可以解析字符串而不是拥有大量合法值。这只是一个例子。但基本点是为此使用自定义类型,而不是 UInt。