Swift小结

作者: 春暖花已开 | 来源:发表于2018-11-26 22:11 被阅读11次

    不同的字符可能会占用不同数量的内存空间,所以要知道Character的确定位置,就必须从String开头遍历每一个 Unicode 标量直到结尾。因此,Swift 的字符串不能用整数(integer)做索引。

    如果两个字符串(或者两个字符)的可扩展的字形群集是标准相等的,那就认为它们是相等的。在这个情况 下,即使可扩展的字形群集是有不同的 Unicode 标量构成的,只要它们有同样的语言意义和外观,就认为它们标 准相等。

    var oddDigits: Set = [1, 3, 5, 7, 9]
    let evenDigits: Set = [0, 2, 4, 6, 8]
    let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
    
    oddDigits.union(evenDigits).sorted() // 取并集
    oddDigits.subtract(singleDigitPrimeNumbers) // 剔除交集
    evenDigits.symmetricDifference(singleDigitPrimeNumbers).sorted() // 交集取反
    
    图片.png

    必须将延迟存储属性声明成变量(使用var关键字),因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。

    当值类型(枚举、结构体)的实例被声明为常量的时候,它的所有属性也就成了常量。属于引用类型的类(class)则不一样。把一个引用类型的实例赋给一个常量后,仍然可以修改该实例的变量属性。

    必须使用var关键字定义计算属性,包括只读计算属性,因为它们的值不是固定的。let关键字只用来声明常量属性,表示初始化后再也无法修改的值。

    跟实例的存储型属性不同,必须给存储型类型属性指定默认值,因为类型本身没有构造器,也就无法在初始化过程中使用构造器给类型属性赋值。存储型类型属性是延迟初始化的,它们只有在第一次被访问的时候才会被初始化。即使它们被多个线程同时访问,系统也保证只会对其进行一次初始化,并且不需要对其使用lazy修饰符。

    func stepForward(_ input: Int) -> Int {
        return input + 1
    }
    
    func stepBackward(_ input: Int) -> Int {
        return input - 1
    }
    
    
    func cal(isAdd: Bool) -> (Int) -> Int {
        if isAdd {
            return stepForward
        }
        return stepBackward
    }
    
    // 等价于
    
    func caculate(isAdd: Bool) -> (Int) -> Int {
        if isAdd {
            func stepFor(input: Int) -> Int {
                return input + 1
            }
            return stepFor
        } else {
            func stepBack(input: Int) -> Int {
                return input - 1
            }
            return stepBack
        }
    }
    
    // 调用1
    cal(isAdd: true)(1)
    // 调用2
    caculate(isAdd: true)(1)
    

    类型属性语法

    在 C 或 Objective-C 中,与某个类型关联的静态常量和静态变量,是作为全局(global)静态变量定义的。但 是在 Swift 中,类型属性是作为类型定义的一部分写在类型最外层的花括号内,因此它的作用范围也就在类型支 持的范围内。
    使用关键字 static 来定义类型属性。在为类定义计算型类型属性时,可以改用关键字 class 来支持子类对父 类的实现进行重写。

    例如:

    struct SomeStructure {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            return 1
        }
    }
    
    enum SomeEnumeration {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            return 6
        }
    }
    
    class SomeClass {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            return 27
        }
        class var overrideableComputedTypeProperty: Int {
            return 107
        }
    }
    
    获取和设置类型属性的值

    跟实例属性一样,类型属性也是通过点运算符来访问。但是,类型属性是通过类型本身来访问,而不是通过实
    例。

    例如:

    print(SomeStructure.storedTypeProperty) // 打印 "Some value." 
    SomeStructure.storedTypeProperty = "Another value." print(SomeStructure.storedTypeProperty) // 打印 "Another value.” 
    print(SomeEnumeration.computedTypeProperty) // 打印 "6" 
    print(SomeClass.computedTypeProperty) // 打印 "27"
    

    在实例方法中修改值类型

    结构体和枚举是值类型。默认情况下,值类型的属性不能在它的实例方法中被修改。
    但是,如果你确实需要在某个特定的方法中修改结构体或者枚举的属性,你可以为这个方法选择 可变(mutatin g) 行为,然后就可以从其方法内部改变它的属性;并且这个方法做的任何改变都会在方法执行结束时写回到原始 结构中。方法还可以给它隐含的 self 属性赋予一个全新的实例,这个新实例在方法结束时会替换现存实例。

    例如:如果没有mutating,将报错Left side of mutating operator isn't mutable: 'self' is immutable

    struct Point {
        var x = 0.0, y = 0.0
        mutating func moveByX(deltaX: Double, y deltaY: Double) {
            x += deltaX
            y += deltaY
        }
    }
    

    枚举的可变方法可以把 self 设置为同一枚举类型中不同的成员:

    例如:

    enum TriStateSwitch {
        case Off, Low, High
        
        mutating func next() {
            switch self {
            case .Off:
                self = .Low
            case .Low:
                self = .High
            case .High:
                self = .Off
            }
        }
    }
    
    var ovenLight = TriStateSwitch.Low
    ovenLight.next() // ovenLight 现在等于 .High
    ovenLight.next() // ovenLight 现在等于 .Off
    

    类型方法

    实例方法是被某个类型的实例调用的方法。你也可以定义在类型本身上调用的方法,这种方法就叫做类型方 法。在方法的 func 关键字之前加上关键字 static ,来指定类型方法。类还可以用关键字 class 来允许子类重写 父类的方法实现。

    注意

    在 Objective-C 中,你只能为 Objective-C 的类类型(classes)定义类型方法(type-level methods)。在 Swift 中,你可以为所有的类、结构体和枚举定义类型方法。每一个类型方法都被它所支持的类型显式包含。


    重写属性

    你可以重写继承来的实例属性或类型属性,提供自己定制的 getter 和 setter,或添加属性观察器使重写的属性 可以观察属性值什么时候发生改变。
    重写属性的 Getters 和 Setters
    你可以提供定制的 getter(或 setter)来重写任意继承来的属性,无论继承来的属性是存储型的还是计算型的 属性。子类并不知道继承来的属性是存储型的还是计算型的,它只知道继承来的属性会有一个名字和类型。你在 重写一个属性时,必需将它的名字和类型都写出来。这样才能使编译器去检查你重写的属性是与超类中同名同类 型的属性相匹配的。
    你可以将一个继承来的只读属性重写为一个读写属性,只需要在重写版本的属性里提供 getter 和 setter 即 可。但是,你不可以将一个继承来的读写属性重写为一个只读属性。

    注意

    如果你在重写属性中提供了 setter,那么你也一定要提供 getter。如果你不想在重写版本中的 getter 里修改 继承来的属性值,你可以直接通过 super.someProperty 来返回继承来的值,其中 someProperty 是你要重写的属 性的名字。

    相关文章

      网友评论

        本文标题:Swift小结

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