我正试着做这样的事情:

typealias HumanId = Int 
typealias RobotId = Int

func getHuman(at index: HumanId) -> Human
func getRobot(at index: RobotId) -> Robot

但就目前而言,我可以用RobotId拨打getHuman:getHuman(at: RobotId(0)).

我怎么才能让这个字体安全呢?


我知道我可以做一些类似的事情:

struct HumanId { let id: Int }
struct RobotId { let id: Int }

...和一些额外的东西来使这些 struct 用作索引,但这会导致一些代码重复,而且由于我有超过2个这样的id类型,我想以某种方式缩短它,使用类型别名和泛型,也许是为了使它们唯一?

推荐答案

您可以利用SWIFT generics来实现您的目标.引入一个通用的Index类型,如下所示:

struct Index<T>: RawRepresentable {
    let rawValue: Int
    init(rawValue: Int) { self.rawValue = rawValue }
    init(_ rawValue: Int) { self.rawValue = rawValue }
}

然后像这样使用它:

func getHuman(at index: Index<Human>) -> Human { ... }
func getRobot(at index: Index<Robot>) -> Robot { ... }

getHuman(at: Index(1))
getRobot(at: Index(2))

文字索引

在使用literal indices时,您甚至可以使用ExpressibleByIntegerLiteral协议来提供一些语法糖分:

extension Index: ExpressibleByIntegerLiteral {
    public init(integerLiteral value: Int) { self.rawValue = value }
}

例如:

getHuman(at: 1)
getRobot(at: 2)

但以下代码将not构建,因此该解决方案仍然是类型安全的:

let someIndex = 123
getHuman(at: someIndex)

error: cannot convert value of type 'Int' to expected argument type 'Index<Human>'

可比指数

正如 comments 中所建议的,我们还可以添加Comparable一致性(例如,这样您就可以在符合标准Collection协议的类型中使用Index struct 作为索引):

extension Index: Comparable {
    static func < (lhs: Index, rhs: Index) -> Bool {
        lhs.rawValue < rhs.rawValue
    }
}

示例:

Index<Human>(1) < Index<Human>(2) // true

Swift相关问答推荐

如何避免使用DispatchSemaphores时线程爆炸?

通常从数组调用的SWIFT静态协议函数

background Task(.backgroundTask)不适用于MySQL

更改 SwiftUI 中按钮矩阵的填充 colored颜色

将 Encodable 扩展添加到 Swift 嵌套枚举

为 ObservedObject 和 State 对象配置预览

如何裁剪图像 3:4 ?迅速

在 Swift 中为(递归)扩展提供默认实例参数

如何 for each 用户制作一个单独的按钮,以便在按下它时切换 isFollowingUser Bool 并更改为关注?

令人满意的 var body:协议扩展中的一些视图

SwiftUI:当先前的视图列表更改时,NavigationView 详细视图会弹出回栈

更改该函数的参数之一时,如何将这些 SwiftUI 异步任务合并到一个任务中以从函数中获得正确的结果

异步等待不会在项目中触发,但在 Xcode playground 中工作正常

阻止其他类型的键盘

Vapor - 流利的,将对象保存到 PostgreSQL

使用自定义相机拍照 iOS 11.0 Swift 4. 更新错误

无法使用锚激活约束

修复 Swift 3 中的警告C-style for Statement is deprecated

UISearchbar TextField 的高度可以修改吗?

swift中相同的数据类型多变量声明