美文网首页swift
# swift - extension

# swift - extension

作者: 开了那么 | 来源:发表于2021-06-24 19:46 被阅读0次

    扩展可以给一个现有的类,结构体,枚举,还有协议添加新的功能。它还拥有不需要访问被扩展类型源代码就能完成扩展的能力(即逆向建模)。扩展和 Objective-C 的分类很相似。(与 Objective-C 分类不同的是,Swift 扩展是没有名字的。)

    Extensions 的作用

    1. Add computed instance properties and computed type properties
      添加计算型实例属性和计算型类属性
    2. Define instance methods and type methods
      定义实例方法和类方法
    3. Provide new initializers
      提供新的构造器
    4. Define subscripts
      定义下标
    5. Define and use new nested types
      定义和使用新的嵌套类型
    6. Make an existing type conform to a protocol
      使已经存在的类型遵循(conform)一个协议

    扩展可以给一个类型添加新的功能,但是不能重写已经存在的功能。

    语法使用
    1、使用 extension 关键字声明扩展

     extension SomeType {
      // 在这里给 SomeType 添加新的功能
    }
    

    2、扩展可以扩充一个现有的类型,给它添加一个或多个协议。协议名称的写法和类或者结构体一样:

    extension SomeType: SomeProtocol, AnotherProtocol {
      // 协议所需要的实现写在这里
    }
    

    3、计算型属性
    扩展可以给现有类型添加计算型实例属性和计算型类属性。这个例子给 Swift 内建的 Double 类型添加了五个计算型实例属性,从而提供与距离单位相关工作的基本支持

    extension Double {
     var km: Double { return self * 1_000.0 }
     var m: Double { return self }
     var cm: Double { return self / 100.0 }
     var mm: Double { return self / 1_000.0 }
     var ft: Double { return self / 3.28084 }
    }
    let oneInch = 25.4.mm
    print("One inch is \(oneInch) meters")
    // 打印“One inch is 0.0254 meters”
    let threeFeet = 3.ft
    print("Three feet is \(threeFeet) meters")
    // 打印“Three feet is 0.914399970739201 meters”
    

    4、构造器
    扩展可以给现有的类型添加新的构造器。它使你可以把自定义类型作为参数来供其他类型的构造器使用,或者在类型的原始实现上添加额外的构造选项。

    扩展可以给一个类添加新的便利构造器,但是它们不能给类添加新的指定构造器或者析构器。指定构造器和析构器必须始终由类的原始实现提供。

    如果你使用扩展给一个值类型添加构造器,而这个值类型已经为所有存储属性提供默认值,且没有定义任何自定义构造器,那么你可以在该值类型扩展的构造器中使用默认构造器和成员构造器。如果你已经将构造器写在值类型的原始实现中,则不适用于这种情况,如同 值类型的构造器委托 中所描述的那样。

    如果你使用扩展给另一个模块中定义的结构体添加构造器,那么新的构造器直到定义模块中使用一个构造器之前,不能访问 self。

    在下面的例子中,自定义了一个的 Rect 结构体用来表示一个几何矩形。这个例子中还定义了两个给予支持的结构体 Size 和 Point,它们都把属性的默认值设置为 0.0:

    struct Size {
        var width = 0.0, height = 0.0
    }
    struct Point {
        var x = 0.0, y = 0.0
    }
    struct Rect {
        var origin = Point()
        var size = Size()
    }
    

    因为 Rect 结构体给所有的属性都提供了默认值,所以它自动获得了一个默认构造器和一个成员构造器,就像 默认构造器 中描述的一样。这些构造器可以用来创建新的 Rect 实例:

    let defaultRect = Rect()
    let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
       size: Size(width: 5.0, height: 5.0))
    

    你可以通过扩展 Rect 结构体来提供一个允许指定 point 和 size 的构造器:

    extension Rect {
        init(center: Point, size: Size) {
            let originX = center.x - (size.width / 2)
            let originY = center.y - (size.height / 2)
            self.init(origin: Point(x: originX, y: originY), size: size)
        }
    }
    

    这个新的构造器首先根据提供的 center 和 size 计算一个适当的原点。然后这个构造器调用结构体自带的成员构造器 init(origin:size:),它会将新的 origin 和 size 值储存在适当的属性中:

    let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
                          size: Size(width: 3.0, height: 3.0))
    // centerRect 的 origin 是 (2.5, 2.5) 并且它的 size 是 (3.0, 3.0)
    

    注意

    如果你通过扩展提供一个新的构造器,你有责任确保每个通过该构造器创建的实例都是初始化完整的。

    方法
    扩展可以给现有类型添加新的实例方法和类方法。在下面的例子中,给 Int 类型添加了一个新的实例方法叫做 repetitions:

    extension Int {
        func repetitions(task: () -> Void) {
            for _ in 0..<self {
                task()
            }
        }
    }
    

    repetitions(task:) 方法仅接收一个 () -> Void 类型的参数,它表示一个没有参数没有返回值的方法。

    定义了这个扩展之后,你可以对任意整形数值调用 repetitions(task:) 方法,来执行对应次数的任务:

    repetitions {
        print("Hello!")
    }
    // Hello!
    // Hello!
    // Hello!
    

    可变实例方法
    通过扩展添加的实例方法同样也可以修改(或 mutating(改变))实例本身。结构体和枚举的方法,若是可以修改 self 或者它自己的属性,则必须将这个实例方法标记为 mutating,就像是改变了方法的原始实现。

    在下面的例子中,对 Swift 的 Int 类型添加了一个新的 mutating 方法,叫做 square,它将原始值求平方:

    extension Int {
        mutating func square() {
            self = self * self
        }
    }
    var someInt = 3
    someInt.square()
    // someInt 现在是 9
    

    下标
    扩展可以给现有的类型添加新的下标。下面的例子中,对 Swift 的 Int 类型添加了一个整数类型的下标。下标 [n] 从数字右侧开始,返回小数点后的第 n 位:

    123456789[0] 返回 9

    123456789[1] 返回 8

    ……以此类推:

    extension Int {
        subscript(digitIndex: Int) -> Int {
            var decimalBase = 1
            for _ in 0..<digitIndex {
                decimalBase *= 10
            }
            return (self / decimalBase) % 10
        }
    }
    746381295[0]
    // 返回 5
    746381295[1]
    // 返回 9
    746381295[2]
    // 返回 2
    746381295[8]
    // 返回 7
    

    如果操作的 Int 值没有足够的位数满足所请求的下标,那么下标的现实将返回 0,将好像在数字的左边补上了 0:

    746381295[9]
    // 返回 0,就好像你进行了这个请求:
    0746381295[9]
    嵌套类型
    扩展可以给现有的类,结构体,还有枚举添加新的嵌套类型:

    extension Int {
        enum Kind {
            case negative, zero, positive
        }
        var kind: Kind {
            switch self {
            case 0:
                return .zero
            case let x where x > 0:
                return .positive
            default:
                return .negative
            }
        }
    }
    

    这个例子给 Int 添加了一个新的嵌套枚举。这个枚举叫做 Kind,表示特定整数所代表的数字类型。具体来说,它表示数字是负的、零的还是正的。

    这个例子同样给 Int 添加了一个新的计算型实例属性,叫做 kind,它返回被操作整数所对应的 Kind 枚举 case 分支。

    现在,任意 Int 的值都可以使用这个嵌套类型:

    func printIntegerKinds(_ numbers: [Int]) {
        for number in numbers {
            switch number.kind {
            case .negative:
                print("- ", terminator: "")
            case .zero:
                print("0 ", terminator: "")
            case .positive:
                print("+ ", terminator: "")
            }
        }
        print("")
    }
    printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
    // 打印“+ + - 0 - 0 + ”
    

    方法 printIntegerKinds(_:),使用一个 Int 类型的数组作为输入,然后依次迭代这些值。对于数组中的每一个整数,方法会检查它的 kind 计算型属性,然后打印适当的描述。

    • 注意 number.kind 已经被认为是 Int.Kind 类型。所以,在 switch 语句中所有的 Int.Kind case 分支可以被缩写,就像使用 .negative 替代 Int.Kind.negative.。

    存储属性和计算属性比较
    1 .计算属性可以用于类、结构体和枚举,存储属性只能用于类和结构体。
    2.存储属性可以是变量存储属性(用关键字 var 定义),也可以是常量存储属性(用关键字 let 定义)。计算属性只能(用关键字 var 定义)。
    3.计算属性不直接存储值,而是提供一个 getter 和一个可 选的 setter,来间接获取和设置其他属性或变量的值。
    4.可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重写属性的方式为继承的属性(包括 存储属性和计算属性)添加属性观察器。你不必为非重写的计算属性添加属性观察器,因为可以通过它的 setter 直接监控和响应值的变化。

    参考:
    swift-book
    Swift计算属性和存储属性

    相关文章

      网友评论

        本文标题:# swift - extension

        本文链接:https://www.haomeiwen.com/subject/jxegyltx.html