swift4.1 系统学习十三 结构体(二)

简介: //// main.swift// swift14(结构体)//// Created by iOS on 2018/10/15.// Copyright © 2018年 weiman. All rights reserved.//import Foundation// 结构体(二)/*继续上节内容,学习结构体的相关知识。

//
// main.swift
// swift14(结构体)
//
// Created by iOS on 2018/10/15.
// Copyright © 2018年 weiman. All rights reserved.
//

import Foundation

// 结构体(二)
/*
继续上节内容,学习结构体的相关知识。
上一节的学习中,我们主要学习了结构体中的属性,包括:
1.存储式实例属性
2.惰性存储式属性
3.计算式属性
4.属性观察者
5.类型属性

本节,我们来学习结构体中的方法,包括:
1.实例方法
2.类型方法
3.初始化器方法
4.逐成员的初始化器方法
5.值类型的初始化器代理
6.可失败的初始化器
7.下标语法
*/

// 1. 实例方法
/*
定义:当我们在枚举、类、结构体类型中定义一个函数时,该函数被称为“方法”。

每个实例方法都具有一个隐式的属性 self ,它指向调用此方法的对象实例,所以self的类型为当前对象的类型。
*/

do {

struct Test {
    // 存储属性
    var a = 10
    
    let s = "hello"
    
    func printS() {
        // 这里,self可以省略。
        print("a = \(a)")
        print("s = \(s)")
    }
    
    // 由于这个方法中,对实例属性进行了修改,所以需要加上mutating关键字。
    mutating func method2(a: Int) {
        // 这里的参数 a 与 实例属性 a重名,所以需要加上self加以区分。
        self.a += a + 1
    }
    
    // 将关联的对象实例重新修改为默认状态。
    mutating func method3() {
        self = Test()
    }
}

var test = Test()
test.method2(a: 10)
test.printS()
test.method3()
test.printS()

}

// 实例方法的引用
/*
由于实例方法必须要与某一对象实例进行关联,所以我们用一个函数引用对象指向某一对象实例的方法时
需要将对象实例也一起带上。
*/

do {

print("\n")

struct Test {
    var property = 100
    
    mutating func method(a: Int) {
        property += a
    }
    
    func foo(_ : Void = ()) {
        print("property = \(property)")
    }
    
    func foo(a: Int) {
        print("value = \(property + a)")
    }
}

var test = Test()
test.property += 10

// 这里通过method方法签名来对它进行调用。
// 由于mutating方法不允许通过函数引用对象对它进行引用,
// 所以这里只能直接通过方法签名做直接调用,
// 这是允许的。
test.method(a:)(5)

let ref = { test.method(a: 6) }
ref()

let ref1 = test.foo(_:)
ref1(())

let ref2 = test.foo(a: )
ref2(10)

/*
 小结:
 对实例方法的引用必须包含与它关联的对象实例。
 */

}

// 2. 类型方法
/*
类型方法与类型属性类似,是与类型相关联的方法,而不是对象实例。
定义一个类型方法也很简单,直接在func 前面添加static就可以了。
如果当前类型是类类型,那么我们还能使用class关键字修饰,表示当前类型方法能够被子类重写。
如果在类类型中用了static关键字修饰,那么该类型方法不允许被子类重写。
*/

do {

print("\n")

struct Test {
    static var a = 100
    
    /// 类型方法
    static func method() {
        // 可以修改类型属性
        self.a += 20
        print("method: a = \(a)")
    }
    
    static func getValue(a: Int) -> Int {
        return self.a + a
    }
    
    static func foo(_: Void) {
        print("这是一个foo")
    }
    
    /// 重载方法
    static func foo(a: Int) {
        print("a = \(a)")
    }
}

// 调用类型方法method
Test.method()

let a = Test.getValue(a: 5)
print("a = \(a)")

var ref = Test.foo(_:)
ref(())

let ref2 = Test.foo(a: )
ref2(1)

/*
 打印结果:
 method: a = 120
 a = 125
 这是一个foo
 a = 1
 */

}

// 3. 初始化器方法
/*
初始化器方法用于在创建一个类、结构体或者枚举类型的对象实例时为该对象的实例属性进行初始化。
在swift中使用init关键字表示当前类型的初始化器方法,然后后面跟着形参列表。
注意:
由于一个类型的初始化器方法肯定返回它所创建的对象实例,因此其返回类型不需要写,就是当前类型本身。
*/

do {

struct Test {
    var a = 10
    let b: Float
    var c: String
    var d: Int?
    
    init() {
        b = 1.0
        self.c = "Hello"
    }
}
// 省略init
var test = Test()
test = Test.init()

let ref = Test.init
test = ref()

}

// 4. 逐成员的初始化器方法
/*
对于结构体类型,有一种默认的初始化形式,叫做逐成员的初始化器方法。
当我们在结构体中定义了一些存储式属性,并没有对他们进行初始化,也没有显示的提供初始化器方法,那么
我们在用该结构体去创建一个对象实例时就可以使用逐成员的初始化方法来为该结构体对象中的每个存储式实例属性
进行指定具体的值。
*/

do {

print("\n")

struct Test: CustomStringConvertible {
    var a = 10
    let b: Float
    var c: String
    var d: Int?
    
    var description: String {
        return "a = \(a), b = \(b), c = \(c), d = \(d)"
    }
}
// 逐成员的初始化器方法
let test = Test.init(a: 10, b: 1.9, c: "生活在社会底层,也要努力活着。", d: 8)
print("test : \(test)")

}

// 5. 值类型的初始化器代理
/*
当我们在一个初始化器方法中调用另一个初始化器方法以执行对一个对象实例的部分初始化,那么这个过程就
叫做初始化器代理。
*/

do {

print("\n")

struct Test {
    var a = 10
    let b: Float
    var c: String
    var d: Int?
    
    init(b: Float) {
        self.b = b
        c = ""
    }
    
    init(b: Float, c: String) {
        self.init(b: b)
        self.c = c
    }
    
    init(b: Float, c: String, d: Int) {
        self.init(b: b, c: c)
        self.d = d
    }
}

var test = Test.init(b: 1.0)
test = Test.init(b: 2.0, c: "OK")
print("test: \(test)")
test = Test.init(b: 3.4, c: "哈啊哈哈", d: 8)
print("test: \(test)")

}

// 6. 可失败的初始化器
/*
有时候需要定义某些类型,这些类型根据用户的输入或者当前的执行环境可能造成其对象实例的创建失败,此时
我们可以使用“可失败的初始化器”。
可失败的初始化器可根据当前条件返回空值。因此,当我们使用可失败的初始化器来创建一个对象时,该对象的
类型为Optional类型。
*/

do {

print("\n")

struct Test {
    var a: Int
    
    init? (value: Int) {
        if value == 0 {
            return nil
        }
        
        a = 100 / value
    }
}

let test = Test(value: 0)
if test == nil {
    print("failed")
} else {
    print("test: \(test)")
}

}

// 7. 下标语法
/*
swift语言中,允许我们在自定义类型中使用下标。
*/

do {

print("\n")

struct Test {
    // 存储式实例属性a
    var a = 10
    
    // 定义下标方法
    subscript(index: Int) -> Int {
        
        get {
            return a + index
        }
        
        set(value) {
            a = value + index
        }
    }
    
    subscript(str: String) -> Int {
        return str.count
    }
    
    subscript(value: Int, str: String) -> Int? {
        get {
            guard let count = Int(str) else {
                return nil
            }
            
            return value + count
        }
        
        set {
            if let data = newValue, let strValue = Int(str) {
                a = value + data + strValue
            }
        }
    }
    
    subscript(_: Void) -> Int {
        
        get {
            return a
        }
        
        set {
            a = newValue
        }
    }
}

var test = Test()
/// 这里调用了test对象的小标方法subscript(index: Int)的setter方法
test[1] = 10
print("test[5] = \(test[5])")
//打印:test[5] = 16

print("count = \(test["abc"])")

test[2, "123"] = 100

print("test: \(test)")

}

// 8. key path
/*
有时候,一个结构体、枚举或者类类型中的某个属性的类型比较复杂,类型嵌套比较深,在swift4中,引入了
Smart KeyPaths这一概念来简化对一些嵌套比较深的属性访问。

*/

do {

print("\n")

struct MyRect {
    
    struct Point {
        var x: Float
        var y: Float
    }
    
    struct Size {
        var width: Float
        var height: Float
    }
    
    var position: Point
    
    var size: Size
}

struct MyStruct {
    var property: Int
    var rect: MyRect
}

/// 这里用Smart KeyPath字面量
/// 定义一个widthKeyPath关键路径,
/// 它是对MyStruct.rect.size.width
/// 这一实例属性的访问路径
let widthKeyPath = \MyStruct.rect.size.width

var obj = MyStruct(property: 10, rect: MyRect(position: MyRect.Point(x: 0.0, y: 1.0), size: MyRect.Size(width: 10.0, height: 20.0)))
let width = obj[keyPath: widthKeyPath]
print("width: \(width)")

obj[keyPath: \MyStruct.rect.position.x] += obj.rect.position.y * 8.0
print("x = \(obj.rect.position.x)")

}

目录
相关文章
|
5月前
|
存储 数据处理 Swift
在Swift中,类(class)和结构体(struct)
在Swift中,类(class)和结构体(struct)
56 1
|
Swift
Swift实用小册08:Class类的Struct结构体的使用
Swift实用小册08:Class类的Struct结构体的使用
266 0
Swift实用小册08:Class类的Struct结构体的使用
|
Swift iOS开发
Swift:暗黑模式iOS 13以上支持是否跟随系统和iOS13以下的主题适配
Swift:暗黑模式iOS 13以上支持是否跟随系统和iOS13以下的主题适配
1429 0
Swift:暗黑模式iOS 13以上支持是否跟随系统和iOS13以下的主题适配
|
存储 编译器 Swift
Swift5.0 - day3-可选项、结构体、类
Swift5.0 - day3-可选项、结构体、类
142 0
Swift5.0 - day3-可选项、结构体、类
|
存储 编解码 编译器
Swift5.1—类和结构体
Swift5.1—类和结构体
115 0
Swift5.1—类和结构体
|
存储 Swift iOS开发
Swift讲解专题十——类与结构体
Swift讲解专题十——类与结构体
99 0
|
存储 Swift
16.Swift学习之结构体
结构体的介绍 概念介绍 结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合 结构体是值类型 结构体既可以定义属性又可以定义方法 定义语法 struct 结构体名称 { // 属性和方法 } 举例 stru...
985 0
|
Swift
swift4.1 系统学习七
import Foundation //swift学习笔记07 /* 控制流语句 学过任何一种语言的小伙伴们都对控制流语句不陌生,几乎每一天都在用。 控制流分类: 1.分支 2.循环 */ /* do语句块 这个语句块在我之前的学习中一直在使用,是一种在学习中很方便的写代码的方式。
1013 0
|
索引 Swift 自然语言处理
swift4.1 系统学习六
swift学习笔记6 字符和字符串 在swift中,String类型也是结构体,属于值类型,而不是引用类型。这一点,与OC是不一样的。 // // main.
842 0
|
存储 Swift iOS开发
swift4.1 系统学习四
// // main.swift // swift04 // // Created by iOS on 2018/9/21. // Copyright © 2018年 weiman.
1060 0