Swift -- 7.4 方法,下标,可选链

方法

swift统一了函数和方法的语法格式,如果函数放在枚举,结构体,类以外定义,就是函数

如果放在枚举,结构体,类以内定义,就是方法

程序可以直接把方法赋值给函数类型的变量

class SomeClass {
    func test()
    {
        print("==test 方法==")
    }
    class func bar(msg:String) {
        print("==bar类型方法==, 传入参数为:\(msg)")
    }
}
var sc = SomeClass()
var f1 : ()->() = sc.test//这里不能加括号,添加括号就变成了方法调用,而不是将方法赋值给函数类型的变量
var f2 : (String)->Void = SomeClass.bar
sc.test()
f1()
SomeClass.bar("test message")
f2("test test test message")

  

结构体和枚举都是值类型,在默认情况下,值类型的实例方法不能改变该实例的存储属性,需要加mutating关键字

struct FkRect {
    var x : Int
    var y : Int
    var width : Int
    var height : Int
    mutating func moveByX(x:Int, y:Int){
        self.x += x
        self.y += y
    }
}
var rect = FkRect(x: 20, y: 12, width: 200, height: 300)
rect.moveByX(100, y: 80)
print("\(rect.x)")
//可以使用可变方法直接改变枚举的实例
enum Planettt:Int
{
    case Mercury = 0, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Nepturn
    mutating func next(){
        if self.rawValue < 8 && self.rawValue > -1
        {
            self = Planettt(rawValue: self.rawValue + 1)!
        }
    }
    mutating func prev(){
        if self.rawValue < 8 && self.rawValue > -1
        {
            self = Planettt(rawValue: self.rawValue - 1)!
        }
    }
}
var pt = Planettt.Venus
pt.next()
pt.next()
pt.prev()

  

方法相当于一种以let声明的、类型为函数类型的存储属性

分析:如果程序使用函数类型定义存储属性,并将函数或闭包作为该属性的初始值,那么这个属性变成了什么呢?没错,这个属性就成了方法

func factorial(n:Int) ->Int
{
    var result = 1
    for idx in 1...n
    {
        result *= idx
    }
    return result
}
struct SomeStruct {
    var info:()->Void={
        print("info")
    }
    static var fact:(Int) -> Int = factorial
}
var sccc = SomeStruct()
sccc.info = {
    print("another bibo")
}
sccc.info()
var n = 6
print(SomeStruct.fact(6))
SomeStruct.fact = {
    var result = 1
    for idx in 1...$0{
        result += idx
    }
    return result
}
print(SomeStruct.fact(6))

  

下标

下标和计算属性非常相似,但是下标比计算属性更灵活

下标的形参列表不支持指定外部参数,也不支持指定默认值

下标重载:一个类型可以包含多个下标,只要多个下标的形参列表不同(形参数量或者形参类型不同)

可以通过扩展来增加下标

struct FkRectt {
    var x : Int
    var y : Int
    var width : Int
    var height : Int
    subscript(idx : Int) -> Int{
        get{
            switch(idx)
            {
            case 0:
                return self.x
            case 1:
                return self.y
            case 2:
                return self.width
            case 3:
                return self.height
            default:
                print("no")
                return 0
            }
        }
        set{
            switch(idx)
            {
            case 0:
                self.x = newValue
            case 1:
                self.y = newValue
            case 2:
                self.width = newValue
            case 3:
                self.height = newValue
            default:
                print("no")
            }
        }
    }
}
var rectc = FkRectt(x: 20, y: 12, width: 3435, height: 3453)
rectc[0] = 40
print(rectc[0])

  

可选链

class Companyy
{
    var name = "feng"
    var addr = "guangzhou"
    init(name:String, addr:String){
        self.name = name
        self.addr = addr
    }
}
class Employeeee
{
    var name = "bai"
    var title = "keke"
    var company : Companyy!
    init(name:String, title:String){
        self.name = name
        self.title = title
    }
    func info(){
        print("name is \(name)")
    }
}
class Customerr
{
    var name = ""
    var emp : Employeeee?
    init(name:String){
        self.name = name
    }
}
var cc = Customerr(name: "sunsun")
var emp = Employeeee(name: "zhu", title: "kekefufu")
cc.emp = emp
emp.company = Companyy(name: "dandan", addr: "panpan")
print("\(cc.name) company is \(cc.emp!.company.name)")
/*
那么问题来了
如果这里的cc没有给emp赋值,那么输出语句会怎么样呢,会报错
这时候可以通过在访问链中强制解析的感叹号(!)换成问号(?),在隐式解析和后面也添加问号(?)后缀,如果其中一个步骤返回nil,那么整个访问链都返回nil,而不会崩溃
eg print("\(cc.name) company is \(cc.emp?.company?.name)")
这就是可选链的访问方式
*/

/*
使用可选链调用方法
*/
class Customeaa
{
    var name = ""
    var emp : Employeeee?
    init(name:String){
        self.name = name
    }
    
    let employees = [
        Employeeee(name: "bai", title: "kefu"),
        Employeeee(name: "zhi", title: "xiaoshou"),
        Employeeee(name: "jin", title: "putonh"),
        Employeeee(name: "xing", title: "zhu")
    ]
    
    func findEmp(empName:String) -> Employeeee!
    {
        for emp in employees{
            if emp.name == empName{
                return emp
            }
        }
        return nil
    }
}
var c3 = Customeaa(name: "fuck")
c3.findEmp("bai").info()//这里没有使用可选链,但是name是存在的,所以不会报错,有输出
c3.findEmp("ba")?.info()//这使用可选链来调用方法,虽然name是错误的,但是不会报错,也没有输出

/*
使用可选链调用下标
*/
var dict = [Int : Customeaa]()
dict[1] = Customeaa(name: "zhu")
dict[2] = Customeaa(name: "sha")
dict[1]?.findEmp("xing")?.info()
dict[4]?.findEmp("xing")?.info()

  

 

posted @ 2016-06-16 15:11  电蚊拍  阅读(178)  评论(0编辑  收藏  举报