swift-06-关键字总结

附上资料地址:w3cschool-Swift 教程Swift中的关键字详解html

1、与声明有关的关键字

  • class:声明一个类,或者类方法
class Person: NSObject {
        
    //声明一个实例方法
    func run() {
        print("run")
    }
    //class修饰表示:声明一个类方法
    class func work() {
        print("work")
    }

}
复制代码
  • struct:声明结构体,内部能够声明成员变量、成员方法。所以更接近于一个类,能够说是类的一个轻量化实现
//声明:
struct Person {
    var name:String
    var age:Int
    
    func introduce(){
        print("我叫:\(name),今年\(age)岁")
    }
}

//调用:
var person = Person(name: "xiaoMing",age: 20)

person.introduce()

//输出:
我叫:xiaoMing,今年20岁
复制代码
structclass比较
struct是结构体,class是类
一、struct是值类型,class是引用类型;意思是:声明一个新的变量指向这个结构体,改变某个属性,本来的结构体属性不会发生变化;而类会随着改变
`
代码示例:

struct myStru {
    var width = 200
}

class myClass {
    var width = 200
}


//调用
var stu = myStru()
var stu2 = stu
stu2.width = 300
print(stu.width,stu2.width)
//200  300


var cls = myClass()
var cls2 = cls
cls2.width = 300
print(cls.width,cls2.width)
//300 300

`
二、struct不能被继承,class能够被继承

三、用let修饰class对象,可以修改类的值;若要修改struct的值,要用var来修饰

四、struct是放在栈上,class是放在堆上,所以struct的访问速度更快

五、struct里面若是想声明一个func来修改声明的属性,须要添加关键字mutating,才能编译成功;而class不须要

六、全部的struct都有一个自动生成的成员构造器,而class须要本身生成

七、在struct中,成员变量能够没有初始值;但在class中,若是成员变量没有初始值,就必须为它写一个构造函数
复制代码
  • static:声明静态变量或者函数,它保证在对应的做用域当中只有一份, 同时也不须要依赖实例化。若是用于修饰函数,表示类方法,且不能被重写
class Person: NSObject {

    var name: String
 
    //类方法,而且该方法不能被子类重写
    static func run() {
        print(self.name + "running")
    }
}
复制代码
staticclass比较
都是放在`func`前面用于指定类方法,只不过`static`修饰的类方法不能够被重写
复制代码
  • typealias:各种起别名
//声明
typealias abc = Int 
//调用
let a:abc = 100 
复制代码
  • enum:枚举,一种常见的数据类型。好处:使用枚举能够防止用户使用无效值,同时该变量可使代码更加清晰。
//写法1,默认赋值0、一、二、3
enum Orientation1:Int{
        case East
        case South
        case West
        case North
    }

//写法2
enum Orientation2:Int{
        case East,South,West,North
}

//调用 具体的值
       print(Orientation1.East.rawValue,Orientation1.South.rawValue,Orientation2.West.rawValue,Orientation2.North.rawValue)
        
//打印
0 1 2 3
        
复制代码
  • extension:拓展,相似oc中的category分类,可是比分类更增强大。通常用于:
    1. 添加计算属性
    2. 添加方法
    3. 添加初始化方法
    4. 添加附属脚本,以下标脚本subscripts
    5. 添加并使用嵌套类型
    6. 遵循并实现某一协议
//给person类添加一个run方法
 class Person: NSObject {
    var name = "swift"
}


extension Person{
    
    func run() {
        print(self.name + "running")
    }
    
}

//调用
let per = Person()
per.run()
复制代码
  • subscript:下标脚本,可让 结构体枚举使用下标功能。须要注意:subscript中能够没有set方法,可是要有get方法
struct Person {
    var age = 0
    var no  = 0
    subscript(index: Int) -> Int {
        set {
            if index == 0 {
                age = newValue
            } else {
                no = newValue
            }
        }
        get {
            if index == 0 {
                return age
            } else {
                return no
            }
        }
    }
}

var p = Person()
p[0] = 10
p[1] = 20

print(p.age)  // 10
print(p[0])   // 10

print(p.no)  // 20
print(p[1])  // 20
复制代码

传多个参数的例子:swift

class Matix {
    var data = [
       [0,0,0],
       [0,0,0],
       [0,0,0]
    ]
    subscript(row: Int , col: Int) -> Int {
        set {
            //守卫,不在这个范围以内的就return
            guard row >= 0 && row < 3 && col >= 0 && col < 3 else {
                return
            }
            data[row][col] = newValue
        }
        get {
            guard row >= 0 && row < 3 && col >= 0 && col < 3 else {
                return 0
            }
            return data[row][col]
        }
    }
}


//调用
var m = Matix()
m[1, 1] = 3
m[0, 1] = 4
//这个超出范围,直接return了
m[4, 4] = 9
print(m.data)

//打印
[[0, 4, 0], [0, 3, 0], [0, 0, 0]]

复制代码
  • init:构造函数,初始化方法
class PerSon: NSObject {
    //若是不给属性直接赋一个初始化值,就必须声明构造函数
    var name:String
    
    init(name : String) {
        self.name = name
    }
    
}

//调用
let person = PerSon.init(name: "xiaoMing")
print(person.name)

//简写
let per = PerSon(name: "xiaoHong")
print(per.name)
复制代码
  • deinit:析构函数,释放方法。与oc中的dealloc同样,用于:对象的销毁、KVO移除、通知移除、NSTimer销毁数组

  • protocol:协议markdown

2、与语句有关的关键字

  • fallthrough:穿透,在switch中,执行完当前case,继续向下执行下一个case
//写法1 = 写法2

let num = 100

//写法1
switch num {
case 100:
    fallthrough
case 200:
    print("100 + 200")
default:
    print("no")
}

//写法2
switch num {
case 100,200:
    print("100 + 200")
default:
    print("no")
}
复制代码
  • where:筛选条件用的,适用于do-catchswitchfor-in泛型协议
let array = [100,-50,36,-8,45]

//遍历数组,只有值大于40的才打印
for i in array where i > 40 {
    print(i)
}

//打印
100
45
复制代码

3、与表达式和类型有关的关键字

  • is:类型检查操做符,检查一个实例是否属于一个特定的子类,是返回true,不是返回false
// 1.定义数组
let array : [Any] = [12, "zhangsan"]

// 2.取出数组中的第一个
let objcFirst = array.first!

// 3.判断第一个元素是不是一个Int类型
if objcFirst is Int {
    print("是Int类型")
} else {
    print("非Int类型")
}
复制代码
  • as:类型转换操做符,向上转型,从派生类转换成基类
//自己根据值定义的是int类型,经过as转换成float类型
var number = 1 as Float
print(number) //1.0

var number = 1 as Float
至关于
var number = Float(1)
复制代码
  • as!:向下转型,转成其子类类型,属于强制转型,若是转换失败会报错闭包

  • as?:规则跟as!同样,若是转换失败,会返回一个nil对象异步

// 1.定义数组
let array : [Any] = [12, "zhangsan"]

// 2.取出数组中最后一个元素
let objcLast = array.last!

// 3.转成真正的类型来使用
// as? 将Any转成可选类型,经过判断可选类型是否有值,来决定是否转化成功了
let name = objcLast as? String
print(name) // 结果:Optional("zhangsan")

// as! 将Any转成具体的类型,若是不是该类型,那么程序会崩溃
let name2 = objcLast as! String
print(name2) // 结果:zhangsan
复制代码

4、特定上下文中的关键字

  • convenience:便利构造函数,用于修饰构造方法init,一般用于对系统类的init构造方法进行扩充,特色:async

    1. convenience一般写在extension
    2. 须要在init以前添加convenience
    3. convenience中须要明确调用self.init()
/*
 对系统的init进行扩充,
 而且这个方法是公共的,
 若是子类要修改,就须要先实现父类方法,不能直接重写
 */
 required convenience public init(...) {
    ...
    self.init()
    ...
 }
复制代码
  • required:只用于修饰类的init初始化方法,表示该初始化方法是必须实现。要求子类必须实现父类的初始化方法

使用规则:ide

  1. 只能用于修饰类初始化方法
  2. 若是子类初始化方法的参数异于父类,要先实现父类的required init方法,这时不能用override,要一样使用required修饰
  3. 若是子类没有init方法,就不用实现父类的required init方法
//子类异于父类init方法状况
class PerSon: NSObject {
    var name: String
    //若是子类要自定义init方法,要先实现父类的
    required init(name: String) {
        self.name = name
    }
}

class Student: PerSon {
    var age: Int = 0
    //先实现父类的
    required init(name:String) {
        super.init(name: name)
    }
    
    //再进行自定义init
    init(firstName: String, age:Int) {
        self.age = age
        super.init(name: firstName)
    }
     
}
复制代码
  • mutating:在结构体或者枚举中,放在func前,表示可修改它所属的实例及实例属性的值。用于在内部成员方法中修改为员变量的值
//正常状况
struct myStruct1 {
    var num1 = 100
    var num2 = 200
    var num3 = 300
 
}

var stu1 = myStruct1()
print(stu1.num1)//100
//直接修改为员变量的值
stu1.num1 = 999
print(stu1.num1)//999


//经过内部方法改变值
struct myStruct2 {
    var num1 = 100
    var num2 = 200
    var num3 = 300
    
    
    mutating func changeNum(mark:Int) {
        self.num1 += mark
    }
}

//调用
var stu2 = myStruct2()
print(stu2.num1)//100
//经过调用结构体的成员方法来修改为员变量的值
stu2.changeNum(mark: 99)
print(stu2.num1)//199
复制代码
  • lazy:懒加载,修饰变量,只有在第一次调用的时候才去初始化值
lazy var first = NSArray(objects: "1","2")
复制代码
  • override:重写父类的方法函数

  • final:能够用来修饰classfuncvar,表示不可重写。能够将类或者类中的部分实现保护起来,从而避免子类破坏oop

  • inout:将值类型的对象 用 引用的方式传递,意思是能够修改外部变量

func test(num: inout Int){
    //若是不加inout,改变外部变量会报错
    num += 1
}

var a = 10
//调用的时候,是取地址操做
test(num: &a)

print(a)//11
复制代码
  • defer:延迟执行,修饰一段函数内任一段代码,使其必须在函数中其余代码执行完毕,函数即将结束前调用;若是有多个defer会自下而上的顺序执行
func test(){
    print("函数开始")
    defer{
        print("执行defer1")
    }
    print("函数将结束")
    defer{
        
        print("执行defer2")
    }
    defer{
        print("执行defer3")
    }
}

//调用
test()

//打印   
函数开始
函数将结束
执行defer3
执行defer2
执行defer1
复制代码

添加异步线程的状况

func test(){
    print("函数开始")
    defer{
        print("执行defer1")
    }
    defer{
        print("执行defer2")
    }
                    DispatchQueue.main.asyncAfter(deadline: .now()+1) {
        print("异步执行完毕")
    }
    print("函数将结束")
    defer{
        print("执行defer3")
    }
}


test()

//打印:
函数开始
函数将结束
执行defer3
执行defer2
执行defer1
异步执行完毕

结论:
异步代码的执行,不会影响defer的执行时间。事实上,defer的执行只和其所在的做用域有关,若是做用域即将被回收,那么会在回收以前执行defer。
复制代码
  • throws:放在可能会出现异常或者错误的函数后面,会把发生的错误带出来,在调用的时候进行错误处理,节省了维护成本;通常调用的时候会配合trydo-catch一块儿使用

代码示例:

//错误类型枚举
enum MyError : Error {
    case ErrorOne
    case ErrorTwo
    case ErrorOther
}


//使用:关键字所在的位置
func thisFuncCouldThrowError(_ type: Int) throws -> String{

    if type == 1 {
        return "成功"
    }else if type == 2{
        throw MyError.ErrorTwo
    }else{
        throw MyError.ErrorOther
    }

}

//调用,配合do-catch进行异常捕捉,抛出异常的方法在调用前要加 try 关键字

do {

    let stu = try thisFuncCouldThrowError(20)
    print("若是出现错误,这里的代码就不会执行了")
    print(stu)

} catch let err as MyError/* 这里若是捕捉到的错误,属于自定义枚举的值,就进行相关处理*/{
    print("出现了错误")
    print(err)
} catch {
    //这里必需要携带一个空的catch 否则会报错。 缘由是可能遗漏
}


//打印
出现了错误
ErrorOther

复制代码
  • rethrows:异常往上传递的关键字,针对的不是函数或者方法的自己,而是它携带的闭包类型的参数,当它的闭包类型的参数throws的时候,咱们要使用rethrows继续将这个异常往上传递, 直到被调用者使用到。这相比throws多一个传递的环节
//throw函数做为闭包参数传入
//throws
func thisFuncCouldThrowError(_ type: Int) throws -> String{

    if type == 1 {
        return "成功"
    }else if type == 2{
        throw MyError.ErrorTwo
    }else{
        throw MyError.ErrorOther
    }

}

//rethrows
func thisFuncRethrows(_ throwsError:(Int) throws -> String) rethrows{

    do {

        let stu = try throwsError(20)
        print("若是出现错误,这里的代码就不会执行了")
        print(stu)

    } catch let err as MyError{
        throw err    //这里进行了 再次throw
    } catch{

    }


}


//调用
let afunc = self.thisFuncCouldThrowError

do {
    try self.thisFuncRethrows(afunc)
    print("没有错误,若是出现错误,这里的代码就不会执行了")
} catch let err as MyError {
    print("出现了错误")
    print(err)
}catch{
    //这里必需要携带一个空的catch 否则会报错。 缘由是可能遗漏
}
复制代码

5、访问权限关键字

swift中提供了5种访问控制的权限: 由低到高:privatefileprivateinternalpublicopen

  • private:只能在当前类class中访问、extension修饰的拓展类中能够访问,可是子类及其余类不可访问
  • fileprivate:只能在当前源文件中访问。也就是说不一样文件中的子类也没法访问
  • internal:默认的访问级别。在源代码所在的整个模块均可以被访问
  • public:能够被任何人访问,在本模块中能够被override(重写)和继承,但在其余的模块中不能够被override和继承
  • open:能够被任何人使用,包含override和继承
相关文章
相关标签/搜索