Swift 方法(Methods)

Method

  • 方法计算型属性的使用选取

1.优先考虑使用 computed property(计算型属性) ,可以利用setter 、getter方法。
2.如果不需要用到setter/getter,并且需要处理数据库相关的复杂任务,那么建议使用方法Method .

struct person {
    var name: String
    
    //很显然可以使用计算型属性来代替
    func age() -> Int {
        return 20
    }
}

Tip: 一个返回单一值的方法,显然没有什么必要存在。

  • self 介绍

一个结构体定义更像是一张蓝图,它的实例 Instance 作为一个真实的对象存在。Swift 编译器默认将self作为一个隐含参数,传递给了method。在结构体内部,允许使用 self 访问实例的属性或方法。

struct person {
    var name: String
    var age: Int
    
    //这种传参方式没有什么意义
    func description(name: String, age: Int) -> String {
        return "\(name)'s age is \(age)"
    }
}

Tip:换句话说,一个实例的方法如果访问的都是自身的属性,那么将他们作为参数传递以增加函数的复杂度是没有任何意义的。


构造函数

之前提到,Swift会根据结构体类型的属性来自动创建构造函数(包含所有属性,强制初始化),这仅仅是为了保证生成实例时保证所有属性是可以使用的状态。

struct Test{
    var name: String
    var age: Int
   /* 
    //这个也被称为 简单构造函数
    init() {
        name = "Tom"
        age = 18
    }
    */
    
    ///自定义构造函数
    func init(name: String, age: Int){
    //这里需要注意 
    /*
        //wrong 不要试图,因为编译器并不会知道哪个才是本地属性
        
        name = name 
        age = age 
        
    */
    
    self.name = name
    self.age = age
    }
    
    
    func description() -> String {
        return  name + String(age)
    }    
}

///注意,如果上面的构造函数处于注释状态,
///那么系统就会强制我们使用系统自动创建的构造函数来进行实例生成。
let test = Test(name: <String>, age: <Int>)

///打开注释,才可以使用已经定义好的 init()构造函数,而自动生成的构造函数会变的不可用。
let testA = Test()

Tip:在你决定创建构造函数时,也就意味着放弃了使用系统为你自动创建好的构造函数。


  • mutating methods (修改实例属性会遇到系统的保护屏障)
struct Test{
    var name: String
    var age: Int
    
    init() {
        name = "Tom"
        age = 18
    }
    
    func description() -> String {
        return  name + String(age)
    }
    
    ///修改age 的方法   
    func changeAge() {
        age += 2
    }    
}

可以看到,我们创建了一个方法用来修改属性age。可以一旦编译,编译器会报如下错误:

Left side of mutating operator isn't mutable: 'self' is immutable

该错误的含义,仿佛是系统在告诉我们self及其属性在结构体中默认是不可变的。当然,这是不包括构造函数的。显然,设计者并不希望我们随意改变内部环境。

  • 思考一: 结构体作为系统提供的最基本数据类型,在某种程度上其类似于OCNSObject的地位。
  • 思考二: 足够微小的基本类型,应该默认是固化的状态。
  • 思考三: 内部不应该含有不直观的、隐藏的状态变更
  • 思考四: 结构体是值类型valueType,copy-on-write
///遵照系统提示,我们会很容易注意到关键字 mutating operator ,修改如下

mutating func changeAge(){
    age += 2
}

//由于结构体是值类型,当期作为参数传递时或者赋值时,默认会发生拷贝操作。那么如果内部存在能够影响属性值的方法,很有可能会导致原结构体和拷贝后的结构体会不一致。

mutating 操作中,Swift会隐含完成以下步骤:

1.被标记为'mutating'的函数,默认调用者将不再是固化的,也就是常量,应该是一个变量。
2.Swift会悄悄的把传入的隐含参数'self',标记为'inout'. 概念上类似于,传址。
  • 类型方法(Type methods)

和类型属性(Type properties)一样,我们也可以自定义类型方法,在类型方法中我们可以访问全部的类型属性。其实这也是另一种单例形式~ 关键字static

Struct Person {
    static func typeFunc(){
        print("do whatever you want...")
    }
}

//调用
Person.typeFunc()

  • 为结构体添加扩展(仅限方法、构造函数、计算型属性)

同OC中类别Category的概念一样,Swift中我们也可以很方便的通过扩展extension为类型添加方法,计算型属性等。

extension Person {
    static func typeFuncA() {
        print("添加类型方法")
    }
    
    static var typeComputeProperty:String {
        return "类型计算型属性"
    }
    
    func instanceFuncA() {
        print("添加实例方法")
    }
    
    var instanceProperty:String {
        return "实例计算型属性"
    }
    
    init() {
        print("添加了构造函数")
    }
    
    
}

上面的是会成功的情况,那么我们做一些错误尝试,来看一下编译器的反应。

///保留上面的扩展,新建一个扩展
extension Person {
    /**
     再次添加一个构造函数   
    */
    init() {
        
    }
    //编译器报错 Invalid redeclaration of 'init()'
    
    /**
    添加一个已有的方法
    */
    func instanceFuncA() {
        print("添加实例方法")
    }  
    //编译器报错 note: 'emptyFunc()' previously declared 
    
    //那么 复写呢
    override func instanceFuncA() {
        print("添加实例方法")
    }
    //结果还是一样的警告,感兴趣的可以试一下复写属性等等
    
}

能够基本得出的结论,Swift 分类中是不能复写类型中已有的函数、属性的。这种限制也很合理,毕竟是不安全的行为。

还有一个有趣的现象,上面已经讲过当你为类型实现了构造函数时,就默认放弃了系统自动生成的构造函数的权利。不过,通过类别,我们可以做到让自定义的构造函数和自动构造函数同时可用。

struct Test{
    var varA:String
    var varB:String
}
//可用
Test(varA: "A",varB: "B")

extension Test{
    init(){
        varA = "A"
        varB = "B"
    }
}

//同时可用
Test()
Test(varA: "A",varB: "B")

在这里给自己留一个问题,为什么Swift不可以添加存储型属性?

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 223,924评论 6 521
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,776评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 170,954评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,576评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,589评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,105评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,480评论 3 427
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,457评论 0 278
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,998评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,026评论 3 343
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,174评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,812评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,502评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,979评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,101评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,674评论 3 380
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,204评论 2 363

推荐阅读更多精彩内容