Swift 中的关键字详解

要学习Swift这门语言,就必须先了解Swift的关键字及对应的解释。这里就列一下在Swift中常用到的关键字。

关键字是类似于标识符的保留字符序列,除非用重音符号(`)将其括起来,否则不能用作标识符。关键字是对编译器具有特殊意义的预定义保留标识符。常见的关键字有以下4种。

 与声明有关的关键字:class、deinit、enum、extension、func、import、init、let、protocol、static、struct、subscript、typealias和var。

与语句有关的关键字:break、case、continue、default、do、else、fallthrough、if、in、for、return、switch、where和while。

表达式和类型关键字:as、dynamicType、is、new、super、self、Self、Type、__COLUMN__、__FILE__、__FUNCTION__和__LINE__。

在特定上下文中使用的关键字:associativity、didSet、get、infix、inout、left、mutating、none、nonmutating、operator、override、postfix、precedence、prefix、rightset、unowned、unowned(safe)、unowned(unsafe)、weak和willSet。

 常见关键字的介绍:

1、class

在Swift当中, 我们使用Class关键字去声明一个类和声明类方法, 比如:

class Person {
        
        // 给方法添加class关键字表示类方法
        class func work() {
            print("Type Method: Person: 学生.")
        }
  
    }

这样我们就声明了一个Student类。

 

2、let

Swift里用let修饰的变量会是一个不可变的常量,即我们不可以对它进行修改。(注意:我们用let修饰的常量是一个类, 我们可以对其所在的属性进行修改)比如:

class Student {
        let name = "xiaoMing"
        var age = 16
        var height = 160
    }

let studen = Student();
        studen.age +=  2
        print("student age is \(studen.age)")
        //输出结果为student age is 18

在Student类里name是不可变的,如果要对它进行修改就要将let改为var。注意:如果这个时候, 再声明一个Student常量去引用student, 那么studen1所指向的内存块是和studen相同的.

 

3、var

Swift中用var修饰的变量是一个可变的变量,即可以对它进行修改。注意:我们不会用var去引用一个类, 也没有必要。比如:

 class Student {
        let name = "xiaoMing"
        var age = 16
        var height = 160
    }

 let studen = Student();
 studen.age +=  2
        
 var student2 = studen;
 student2.age -=  3
 print("student age is \(studen.age)")
 print("student2 age is \(student2.age)")
        
 /**
 输出结果为
 student age is 15
 student2 age is 15
*/

由输出结果可以看出他们所指向的内存块都是同一个。

 

4、struct

在Swift中, 我们使用struct关键字去声明结构体,Swift中的结构体并不复杂,与C语言的结构体相比,除了成员变量,还多了成员方法。使得它更加接近于一个类。个人认为可以理解为是类的一个轻量化实现。比如:

struct Person {
        var name:String
        var age:Int
        
        func introduce(){
            print("我叫:\(name),今年\(age)岁")
        }
    }

var person = Person(name: "xiaoMing",age: 20)
person.name = "xiaoMing"
print("person.name = \(person.name)")
person.introduce()
        
 /**
 输出结果为:
 person.name = xiaoMing
 我叫:xiaoMing,今年20岁
 */

语法与C语言或者OC类似,Swift中的结构体,在定义成员变量时一定要注明类型。另外要注意一下的是,结构体属于值类型,而Swift中的类属于引用类型。他们在内存管理方面会有不同。

 

5.enum

在Swift中, 我们使用enum关键字去声明枚举。枚举是一种常见的数据类型,他的主要功能就是将某一种有固定数量可能性的变量的值,以一组命名过的常数来指代。比如正常情况下方向有四种可能,东,南,西,北。我们就可以声明一组常量来指代方向的四种可能。使用枚举可以防止用户使用无效值,同时该变量可以使代码更加清晰。比如:

enum Orientation:Int{
        case East
        case South
        case West
        case North
    }
    /**
     或者
    enum Orientation:Int{
     case East,South,West,North
     }
     */

print(Orientation.East.rawValue)
        /**
         输出结果 0
         
         */

注意:我们在定义枚举时,一定要指定类型,否则在使用时就会报错。枚举类型的值如果没有赋值,他就按照默认的走,可以赋予我们自己想要的值。

 

6、final

Swift中,final关键字可以在class、func和var前修饰。表示 不可重写 可以将类或者类中的部分实现保护起来,从而避免子类破坏。详细了解可以去看看(Swift - final关键字的介绍,以及使用场景

)。比如:

  class Fruit {
        //修饰词 final 表示 不可重写 可以将类或者类中的部分实现保护起来,从而避免子类破坏
        final  func price(){
            print("price")
        }
    }
    
    class Apple : Fruit {//类继承
//        //重写父类方法
//        override func price() {
//            print("重写父类的price 方法")
//        }
}

这里重写 price()这个函数就会报错。

 

7、override

在Swift中, 如果我们要重写某个方法, 或者某个属性的话, 我们需要在重写的变量前增加一个override关键字, 比如:

class Fruit {
        var  sellPrice : Double = 0
        
        func info() -> () {
            print("fruit")
        }
        //修饰词 final 表示 不可重写 可以将类或者类中的部分实现保护起来,从而避免子类破坏
        final  func price(){
            print("price")
        }
    }
    
    class Apple : Fruit {//类继承
        func eat () -> () {
            print("apple22222")
        }
        //重写父类方法
        override func info() {
            print("重写父类的info 方法00000")
        }
        //重写父类的属性  重写父类的属性或者方法要使用关键字 override 进行修饰
        override var sellPrice: Double {
            get {
                print("kkkkkkk\(super.sellPrice)")
                return super.sellPrice + 3
            }
            set {
                print("qqqqq")
                super.sellPrice = newValue * newValue
            }  
        }  
    }  


        let app = Apple()
        app.info()
        app.sellPrice = 20.0
        let  adb = app.sellPrice
        
        print("adb == \(adb)")
        
        /**
         输出结果为:
         重写父类的info 方法00000
         qqqqq
         kkkkkkk400.0
         adb == 403.0
         */
    

 

8、subscript

在Swft中,subscript关键字表示下标,可以让class、struct、以及enum使用下标访问内部的值。其实就可以快捷方式的设置或者获取对应的属性, 而不需要调用对应的方法去获取或者存储, 比如官网的一个实例:

struct Matrix {
        let rows: Int, columns: Int
        var grid: [Double]
        init(rows: Int, columns: Int) {
            self.rows = rows
            self.columns = columns
            grid = Array(repeating: 0.0, count: rows * columns)
        }
        
    
        func indexIsValid(row: Int, column: Int) -> Bool {
            return row >= 0 && row < rows && column >= 0 && column < columns
        }
        subscript(row: Int, column: Int) -> Double {
            get {
                assert(indexIsValid(row: row, column: column), "Index out of range")
                return grid[(row * columns) + column]
            }
            set {
                assert(indexIsValid(row: row, column: column), "Index out of range")
                grid[(row * columns) + column] = newValue
            }
        }
    }

var matrix = Matrix(rows: 2, columns: 2)
        matrix[0, 1] = 1.5
        matrix[1, 0] = 3.2
        print("matrix == \(matrix)")
        /**
         打印结果:
         matrix == Matrix(rows: 2, columns: 2, grid: [0.0, 1.5, 3.2000000000000002, 0.0])
         
         */

 

9、static

Swift中,用static关键字声明静态变量或者函数,它保证在对应的作用域当中只有一份, 同时也不需要依赖实例化。注意:(用static关键字指定的方法是类方法,他是不能被子类重写的)比如:

    class Person {
        
        // 给方法添加class关键字表示创建类方法
        class func work() {
            print("Type Method: Person: 学生.")
        }
        
        // 使用static关键字创建类方法
        static func ageOfPerson(name: String) {
            print("Type Method: Person name: \(name)")
        }
        
        // 可以和类方法重名, 以及一样的参数.
        func nameOfPerson(name: String) {
            print("Instance Method: person name \(name)")
        }
        
    }
    
    class Student: Person {
        
        //注意 子类Student的实例方法work(), 和父类的类方法work()没有关系, 二者不在同一个级别上, 不存在同名问题.
        func work() {
            print("Instance Method: Student: University Student")
        }
    }

 

10、mutating

Swift中,mutating关键字指的是可变即可修改。用在structure和enumeration中,虽然结构体和枚举可以定义自己的方法,但是默认情况下,实例方法中是不可以修改值类型的属性。为了能够在实例方法中修改属性值,可以在方法定义前添加关键字mutating。比如:

 

struct rect {
        var width = 0,height = 0
        mutating func changeRect(x:Int, y:Int) {
            self.width += x
            self.height += y
        }
        
    }
    
   
    enum Direction {
        case Top, Left, Right, Bottom
        mutating func lookDirection() {
            switch self {
            case .Top:
                self = .Top
            case .Left:
                self = .Left
            case .Right:
                self = .Right
            case .Bottom:
                self = .Bottom
            }
            print("self === \(self)")
        }
    }


    var re = rect(width: 5, height: 5)
        re.changeRect(x: 32, y: 15)
        print("re = \(re)")
        
        /**
         打印结果为:re = rect(width: 37, height: 20)
         */
        
        var dir = Direction.Left
        dir.lookDirection()
        /**
         打印结果为:self === Left
         */

    

 

11、typealias

在Swift中,使用关键字typealias定义类型别名(typealias就相当于objective-c中的typedef),就是将类型重命名,看起来更加语义化。比如:

typealias Width = CGFloat
        typealias Height = CGFloat
        func rectangularArea(width:Width, height:Height) -> Double {
            return Double(width*height)
        }
        let area: Double = rectangularArea(width: 10, height: 20)
        print(area)
        
        /**
         结果为:200.0
         */

 

12、lazy

在Swift中,lazy关键修饰的变量, 只有在第一次被调用的时候才会去初始化值(即懒加载)。比如:

lazy var first = NSArray(objects: "1","2")

注意:用lazy修饰的变量必须是用var声明的, 因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。如果被lazy修饰的变量没有在初始化时就被多个线程调用, 那就没有办法保证它只被初始化一次了。

 

13、init

在Swift 中,init关键字也表示构造器。比如:

class PerSon {
        var name:String
        init?(name : String) {
            if name.isEmpty { return nil }
            self.name = name
        }
        
    }

let person = PerSon.init(name: "xiaoQiang")
        print("person is name \(String(describing: person?.name))")

/**
打印结果为:person is name Optional("xiaoQiang")
*/

在例子里在init后面加个”?”号, 表明该构造器可以允许失败。

 

14、required

在Swift里,required是用来修饰init方法的,说明该构造方法是必须实现的。比如:

 class PerSon {
        var name:String
        required init(name : String) {
            self.name = name
        }
    }
    
    class Student: PerSon {
        required init(name:String) {
            super.init(name: name)
        }
    }

从上面的代码示例中不难看出,如果子类需要添加异于父类的初始化方法时,必须先要实现父类中使用required修饰符修饰过的初始化方法,并且也要使用required修饰符而不是override

注意: (1)required修饰符只能用于修饰类初始化方法。

    (2)当子类含有异于父类的初始化方法时(初始化方法参数类型和数量异于父类),子类必须要实现父类的required初始化方法,并且也要使用required修饰符而不是override

    (3)当子类没有初始化方法时,可以不用实现父类的required初始化方法。

 

15、extension

在swift中,extension与Objective-C的category有点类似,但是extension比起category来说更加强大和灵活,它不仅可以扩展某种类型或结构体的方法,同时它还可以与protocol等结合使用,编写出更加灵活和强大的代码。它可以为特定的class, strut, enum或者protocol添加新的特性。当你没有权限对源代码进行改造的时候,此时可以通过extension来对类型进行扩展。extension有点类似于OC的类别 -- category,但稍微不同的是category有名字,而extension没有名字。在Swift 中的可以扩展以下几个:

  (1)定义实例方法和类型方法

  (2)添加计算型属性和计算静态属性

  (3)定义下标

  (4)提供新的构造器

  (5)定义和使用新的嵌套类型

  (6)使一个已有类型符合某个接口

比如:

//    添加计算属性
extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
}
class Person {
    var name:String
    var age:Int = 0
    init?(name:String) {
        if name.isEmpty {
            return nil
        }
        self.name = name
    }
    
}

extension Person {
    //添加方法
    func run() {
        print("走了50公里")
    }
}


 let oneInch = 25.4.km
        print("One inch is \(oneInch) meters")
        /**
         
         输出结果:One inch is 25400.0 meters
         */
        
        let person = Person.init(name: "xiaom")
        person?.run()
        /**
         
         输出结果:走了50公里
         */

想要了解详情可以去看看这篇文涨(apple documents - extensions

 

16、convenient

swift中,使用convenience修饰的构造函数叫做便利构造函数 。便利构造函数通常用在对系统的类进行构造函数的扩充时使用。便利构造函数有如下几个特点:  

  (1)便利构造函数通常都是写在extension里面  

  (2)便利函数init前面需要加载convenience   

  (3)在便利构造函数中需要明确的调用self.init()  

比如:

extension UIButton{
    //swit中类方法是以class开头的方法,类似于oc中+开头的方法
    class func createButton(imageName:String)->UIButton{
        
        let btn=UIButton()
        btn.setImage(UIImage(named:imageName), for: .normal)
        btn.sizeToFit()
        
        return btn
    }
    /*
     convenience:便利,使用convenience修饰的构造函数叫做便利构造函数
     便利构造函数通常用在对系统的类进行构造函数的扩充时使用。
     
     */
    
    convenience init(imageName:String,bgImageName:String){
        self.init()
        if !imageName.isEmpty {
            setImage(UIImage(named:imageName), for: .normal)
        }
        if !imageName.isEmpty {
            setBackgroundImage(UIImage(named:bgImageName), for: .normal)
        }
        sizeToFit()
    }
}


let btn = UIButton.init(imageName: "huanying", bgImageName: "")
        btn.frame = CGRect.init(x: 10, y: 120, width: 100, height: 30)
        btn.backgroundColor = UIColor.red
        self.view.addSubview(btn)

 

17、deinit

在Swift中,deinit属于析构函数,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。和OC中的dealloc 一样的,通常在deinit和dealloc中需要执行的操作有:  

  (1)对象销毁

  (2)KVO移除

  (3)移除通知

  (4)NSTimer销毁

 

18、fallthrough

 swift语言特性switch语句的break可以忽略不写,满足条件时直接跳出循环.fallthrough的作用就是执行完当前case,继续执行下面的case.类似于其它语言中省去break里,会继续往后一个case跑,直到碰到break或default才完成的效果。比如:

        var myClass = MyClass(parm: 9)
        let index = 15
        switch index {
            case 1  :
                print( "index is 100")
            case 10,15  :
                print( "index is either 10 or 15")
            case 5  :
                print( "index is 5")
            default :
                print( "default case")
        }
        
        /**
         输出结果:index is either 10 or 15
         */

  let index = 15
        switch index {
        case 100  :
            print( "index is 100")
            fallthrough
        case 10,15  :
            print( "index is either 10 or 15")
            fallthrough
        case 5  :
            print( "index is 5")
        default :
            print( "default case")
        }

/**

打印结果:
    index is either 10 or 15
    index is 5
    
*/

 

19、protocol

在Swift中,protocol关键字也是属于协议。比如:

protocol PersonProtocol {
    var height: Int { get set }
    var weight: Int { get }
    func getName()
    func getSex()
    func getAge(age: Int)
}

struct Student: PersonProtocol {
    var height = 178
    var weight = 120
    func getName() {
        print("MelodyZhy")
    }
    func getSex() {
        print("boy")
    }
    func getAge(age: Int) {
        print("age = \(age)")
    }
}

 var stu = Student()
        let height1 = stu.height
        stu.height = 180
        print("height1 = \(height1) height2 = \(stu.height)")
        
        /**
         输出结果:
         height1 = 178 height2 = 180
         */

 

20、open

在Swift中,open修饰的对象表示可以被任何人使用,包括override和继承。例如:

import UIKit
// 在本类外的范围外可以被继承
open class ParentClass1: NSObject {
    // 这个方法在任何地方都可以被override
    open func abc() {
        print("abc")
    }
}class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //这里可以调用module1的方法
        let child = ChildrenClass1.init()
        child.abc()
        /**
         打印结果:abc
         */
    }

    class ChildrenClass1: ParentClass1 {
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

 

21、public

在Swift中,public表示公有访问权限,类或者类的公有属性或者公有方法可以从文件或者模块的任何地方进行访问。但在其他模块(一个App就是一个模块,一个第三方API, 第三等方框架等都是一个完整的模块)不可以被override和继承,而在本模块内可以被override和继承。

import UIKit
// 在module1外的范围外可以被继承
public class ParentClass1: NSObject {
    // 这个方法在任何地方都可以被override
   public func abc() {
        print("abc")
    }
}class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //这里可以调用module1的方法
        let child = ChildrenClass1.init()
        child.abc()
        
        /**
         打印结果:abc11
         */
    }

class ChildrenClass1: ParentClass1 {
        override func abc() {
            print("abc11")
        }
    
        func run() -> Void {
            print("run")
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

 

22、internal

在Swift中,public表示内部的访问权限。即有着internal访问权限的属性和方法说明在模块内部可以访问,超出模块内部就不可被访问了。在Swift中默认就是internal的访问权限。

import UIKit

// 在module1外的范围外可以被继承
internal class ParentClass1: NSObject {
    // 这个方法在任何地方都可以被override
    func abc() {
        print("abc")
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //这里可以调用module1的方法
        let child = ChildrenClass1.init()
        child.abc()
        
        /**
         打印结果:abc11
         */
    }

class ChildrenClass1: ParentClass1 {
        override func abc() {
            print("abc11")
        }
    
        func run() -> Void {
            print("run")
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

 

23、private

在Swift中,private私有访问权限。被private修饰的类或者类的属性或方法可以在同一个物理文件中访问。如果超出该物理文件,那么有着private访问权限的属性和方法就不能被访问。比如:

import UIKit

// 在module1外的范围外可以被继承
internal class ParentClass1: NSObject {
    // 这个方法在任何地方都可以被override
 private func abc() {
        print("abc")
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //这里可以调用module1的方法
        let child = ChildrenClass1.init()
        child.abc()
        
        /**
         打印结果:abc11
         */
    }

class ChildrenClass1: ParentClass1 {
    
    /**
     这里就会报错
     */
    
    override func abc() {
        print("abc11")
    }
}
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

 

24、fileprivate

在Swift中,fileprivate访问级别所修饰的属性或者方法在当前的Swift源文件里可以访问。比如:

import UIKit

// 在module1外的范围外可以被继承
internal class ParentClass1: NSObject {
    // 这个方法在任何地方都可以被override
 fileprivate func abc() {
        print("abc")
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //这里可以调用module1的方法
        let child = ChildrenClass1.init()
        child.abc()
        
        /**
         打印结果:abc11
         */
    }

class ChildrenClass1: ParentClass1 {
    
    override func abc() {
        print("abc11")
    }
}
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

说明:5种修饰符访问权限排序open> public > interal > fileprivate > private。

 

 

参考文献:

  http://www.jianshu.com/p/6daa3e309235

  http://blog.csdn.net/qq350116542/article/details/50629260

  http://www.jianshu.com/p/1ae8c364954a 

posted @ 2017-09-15 16:25  微笑着转身  阅读(5444)  评论(0编辑  收藏  举报