TypeBurritoFramework 1.1.3

TypeBurritoFramework 1.1.3

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布的最后发布2016年6月
SPM支持 SPM

Atai Barkai 维护。



TypeBurritoFramework


它是什么?

TypeBurritoFramework 是一个 Swift 微框架,它使创建包装特定情况下使用的原始类型的类型变得 快速无样板,并允许类型检查器强制执行安全使用。

  • 与运行时数据转换和检查清晰耦合。
  • 目的


允许将类型视为 限制 而不仅仅是 数据持有者,从而提高代码的 安全性清晰性

灵感


https://realm.io/news/altconf-justin-spahr-summers-type-safety/


A type which adopts TypeBurrito automatically receives reasonable behavior and compliance for

hashValue (Hashable -> can be used as a dictionary key)

  • <, == (Comparable, but only across the same subtype)
  • it is CustomStringConvertible, meaning we can print it and use it inside Strings
  • it is CustomDebugStringConvertible
  • If the underlying type wrapped by a TypeBurrito is a number, then we also automatically get

+ (but only across the same subtype)

  • - (but only across the same subtype)
  • += (but only across the same
  • subtype)
  • -= (but only across the same


subtype)

import TypeBurritoFramework

TypeBurrito 声明

enum SQLQuery_Spec: TypeBurritoSpec { typealias TheTypeInsideTheBurrito = String }
typealias SQLQuery = TypeBurrito<SQLQuery_Spec>

enum Meters_Spec: TypeBurritoSpec { typealias TheTypeInsideTheBurrito = Double }
typealias Meters = TypeBurrito<Meters_Spec>

enum Inches_Spec: TypeBurritoSpec { typealias TheTypeInsideTheBurrito = Double }
typealias Inches = TypeBurrito<Inches_Spec>

实际中的 TypeBurrito

let query = SQLQuery("SELECT * FROM SwiftFrameworks")
let metersClimbedToday = Meters(40) + Meters(2)
let truth = ( Meters(1000) > Meters(34) )

var distanceLeft = Meters(987.25)
distanceLeft -= Meters(10)

let lengthOfScreenDiagonal = Inches(13)

func performSQLQuery(sqlQuery: SQLQuery){
    // can only be called with a SQLQuery, not with just any String
}

以下内容如果未注释将会是编译时错误

//let _ = Meters(845.235) + Inches(332)

gatewayMap 函数

我们还可以使用静态函数 gatewayMap 定义 TypeBurritoSpec,其中

static func gatewayMap(preMap: TheTypeInsideTheBurrito) -> TheTypeInsideTheBurrito

网关映射允许我们构建在允许值范围内具有 固有 限制的类型。

例如,我们可以构建一个具有自然不区分大小写的 Username 类型。这是通过有一个将任何输入转换为小写版本的 gatewayMap 来实现的。

enum _Username: TypeBurritoSpec {
    typealias TheTypeInsideTheBurrito = String

    static func gatewayMap(preMap: TheTypeInsideTheBurrito) -> TheTypeInsideTheBurrito{
        return preMap.lowercaseString
    }
}
typealias Username = TypeBurrito<_Username>

从那一刻起,我们可以确定,如果给出了一个 Username,无论其是由小写还是大写字母构成,这都是无关紧要的。

let lowercaseSteve = Username("[email protected]")
let uppercaseSteve = Username("[email protected]")

assert(lowercaseSteve == uppercaseSteve)

当我们的值受到对我们的“心理”模型类型中固有的限制,但在底层数据类型中不具有这种限制时,gatewayMap 可以派上用场。

例子包括

  • 一个始终进行 URL 编码的 URL 类型
  • 一个始终进行 SQL 编码(且不易受到 SQL 注入攻击)的 SQLCommand 类型
  • 一个不允许低于 -1 或高于 72(SomeBuilding 的最低和最高层)的 LevelInSomeBuilding 类型
  • 等等。

我们仍然有与运行时行为而不是编译时行为相关的“类型信息”,但此信息(以及所有相关测试!)现在仅限于 gatewayMap() 函数。

高级用法:FailableTypeBurrito

存在一个与 TypeBurrito 直接对应的 FailableTypeBurrito(以及相应的 FailableTypeBurritoSpec)。

然而,它的 gatewayMap 函数可能会返回 nil,这将导致 FailableTypeBurritonil

例如

enum EnglishLettersOnlyString_Spec: FailableTypeBurritoSpec {
    typealias TheTypeInsideTheBurrito = String

    static func gatewayMap(preMap: TheTypeInsideTheBurrito) -> TheTypeInsideTheBurrito? {

        if(preMap.stringByTrimmingCharactersInSet(NSCharacterSet.letterCharacterSet()) == "") {
            return preMap
        }
        else{
            return nil
        }
    }
}
typealias EnglishLettersOnlyString = FailableTypeBurrito<EnglishLettersOnlyString_Spec>

以下内容仅由英文字符组成,因此结果值为非 nil

let actuallyOnlyLetters = EnglishLettersOnlyString("abclaskjdf")

以下内容 仅由英文字符组成,因此结果值为 nil

let notOnlyLettes = EnglishLettersOnlyString("asdflkj12345")

安装