Swift的第二周爬坑之路

今天没有没有心灵砒霜。
那是因为独木舟曾说过——那一刻你的心里有场海啸,可你静静地,没让任何人知道......


Point 1:集合
//1.集合的创建
var a:Set<Int> = [2,3,12,24,3,2]
//其实集合的创建多了个Set类型

print(a)
//打印结果:[12,24,2,3]
//这里排除了所有重复的元素,并且由哈希算法进行的无序排位
//2.集合的元素添加以及删除
a.insert(100)
//在集合a中插入"100"这个元素
a.remove(2)
//在集合a中删除"2"这个元素
//3.集合的运算
var a:Set<Int> = [2,3,12,24,3,2]
var b: Set<Int> = [3, 5, 7, 9, 11]
a.intersect(b)
//交集(a和b都有的元素)
//打印结果为:[3]
a.union(b)
// 并集(a和b的所有元素)
//打印结果为:[12, 2, 9, 5, 7, 24, 3, 11]
print(a.subtract(b))
// 差集(a有b没有的元素)
//打印结果为:[12, 24, 2]

Point 2:字典——是语言就该有字典,程序语言也不例外

①.字典是存放键值对组合的容器,字典中的每个元素都是由两部分构成的, 冒号前面是键冒号后面是值。

var dict: [String : String] = ["1" : "吃饭" , "2" : "睡觉" , "3" : "打豆豆"]
//字典的定义

print(dict["1"])
//过键获取对应的值
//打印结果:吃饭

②.元素的增删改

//元素的添加
dict["4''] = "去成都看海" //关键字[键] = 值 和数组有点相似
print(dict)
//打印结果: ["1" : "吃饭" , "2" : "睡觉" , "3" : "打豆豆" , "4" : "去成都看海"]

//元素的删除
dict.removeValueForKey("2")
print(dict)
//打印结果:["1" : "吃饭" , "3" : "打豆豆" , "4" : "去成都看海"]

dict["3"] = nil
print(dict)
//["1" : "吃饭" , "4" : "去成都看海"]

//元素的修改
dict["4"] = "去成都看海看海看海"
print(dict)
//["1" : "吃饭" , "4" : "去成都看海看海看海"]

③.字典的遍历——和数组一样有 字典名.属性(属性通常是keys、values)

//// 遍历字典中所有的值
for value in dict.values {
    print(value)
}

// 遍历字典中所有的键
for key in dict.keys {
    print("\(key) ---> \(dict[key])")
}

// 直接通过一个元组获得字典中的键和值(原始类型)___★★★★★
          
for (key, value) in dict {
    print("\(key) ---> \(value)")
}

Point 3:数组又解
let array = [23, 37, 96, 55, 40, 92, 68, 88]

// 1. 过滤
let newArray1 = array.filter { $0 > 50 }
print(newArray1)
//打印结果:[96, 55, 92, 68, 88]

let newArray2 = array.filter { $0 % 2 == 0 }
print(newArray2)
//打印结果:[96, 40, 92, 68, 88]
// 2. 映射
let newArray3 = array.map { $0 * $0 }
print(newArray3)
//打印结果:[529, 1369, 9216, 3025, 1600, 8464, 4624, 7744]

// 3. 缩减
let result1 = array.reduce(0, combine: +)
print(result1)
//打印结果:499

Point 4:函数
//函数的构建
由关键字func引导 + 函数名(参数)+ -> 返回值类型 {
      函数体
      //如果函数的返回类型不是void 那么函数中一定有return语句
}
例:
func sayHello(personName: String) -> String {
    let greeting = "Hello, " + personName + "!"
    return greeting
print(sayHello("Xyk_"))
// 调用Swift的函数时, 在默认情况下从第二个参数开始需要写参数名
//第一个参数名加上,第二个到以后的参数名都加上,就构成了外部参数名。
//录入时记得加上(代码提示功能会自动补全)
func sum(a a:Int = 0,b b:Int = 0,c c:Int = 0) -> Int{
    return a + b + c
}
print(sum())
print(sum(a: 1, b: 2, c: 3))
// 函数调用传参都是传值
// Swift中函数的参数列表可以是可变参数列表(参数的个数是任意多个)
func sum(nums: Int...) -> Int {
    var total = 0
    for num in nums {
        total += num
    }
    return total
}

inout 用于内部函数名前面,不仅可以作为输入参数还可以作为输出函数
// inout - 输入输出参数(不仅将数据传入函数还要从函数中取出数据)
func createX(inout x: Int) {
    x = 1000
}

var x = 1
// inout类型的参数前要加上&符号
createX(&x)
print(x)
// 可以使用元组(tuple)让函数一次返回多条数据

函数的扩展
在Swift中函数是一种类型
这也就意味着函数可以作为变量或常量的类型
同理函数也可以作为另一个函数的参数或返回值

func sum(a a: Int,  b: Int) -> Int {
    return a + b
}

// 当调用foo函数时第二个参数可以传什么?
func foo(array: [Int], fn: (Int, Int) -> Int) -> Int {
    var sum = array[0]
    for x in array[1..<array.count] {
        sum = fn(sum, x)
    }
    return 0
}

func sum(a: Int, _ b: Int) -> Int {
    return a + b
}


let a = [1, 2, 3, 4, 5]
//回答如下:
// 1. 所有自定义的(Int, Int) -> Int类型的函数
print(foo(a, fn: sum))
// 2. 传入已有的二元运算符: +-*/%(因为运算符也是函数)
print(foo(a, fn: +))
// 3. 传入匿名函数(闭包)
// 3.1 完整的闭包写法
print(foo(a, fn: { (a, b) -> Int in
    return a + b
}))
// 3.2 省略掉类型和不必要的括号
print(foo(a, fn: { a, b in a + b }))
// 3.3 省略参数名
print(foo(a, fn: { $0 + $1 }))
// 3.4 尾随闭包
print(foo(a) { (a, b) -> Int in
    return a + b
})
print(foo(a) { $0 + $1 })

// 如果函数的最后一个参数是闭包可以写成尾随闭包的形式
// 也就是将闭包放到函数参数的圆括号外面写在一对花括号中
// 如果函数后面有尾随闭包且函数的圆括号中没有参数
// 那么函数的圆括号也可以省略(仅限于有尾随闭包的场景)
array.sortInPlace { $0 > $1 }

Point5:自定义类

步骤1: 定义类(如果你要用的类苹果已经提供了就直接进入第2步)

class 类名 {
       定义类的属性,
      //var name: String

     // 初始化方法(构造方法/构造器) - constructor
      init(参数:类型) { //例如:name: String 是要传出去调用的
     //self.name = name 因为重名,所以用self
      }

   func 方法名 {
       方法的执行体
    }
}

步骤2: 创建对象(调用初始化方法)

let stu1 = 类名(参数名:参数值)

步骤3: 给对象发消息(通过给对象发消息来解决问题)

stu1.上述的方法名() 

类的拓展1
知识点:
1.1 级联编程
1.2 运算符重载
1.3 注释

这次以一个例题来讲解这三个知识点——分数的计算
本次的分数计算的代码有点多,仅写一个加法方法的注释块代码来演示,所以我在这里先将里面的大纲提取出来:
  1.首先先创建一个叫做Fraction的分数类,其中包含分子分母的存储属性定义、初始化函数的构造
  2.分别写上加减乘除的方法,其中的参数是另一个Fraction,返回值类型也是Fraction类型。_num * other._num 就表示自身有的分子和传入的分子相乘。
  3.对相乘后的函数进行简化(simplify())和符号正规化(normalize())——ps:gcd()函数用于分数的化简
  4.最后是函数的运算符重载

代码演示:

// 短除法 -  x和y的最大公约数跟y%x和x的最大公约数是一样的
func gcd(x: Int, _ y: Int) -> Int {  //求最大公约数函数
    if x > y {
        return gcd(y, x)
    }
    else if y % x != 0 {
        return gcd(y % x, x)
    }
    else {
        return x
    }
}

//创建一个叫做Fraction的类
class Fraction {
    private var _num: Int //分子
    private var _den: Int //分母
    
    var info: String {
        get {
            return _num == 0 || _den == 1 ? "\(_num)" : "\(_num)/\(_den)"
        }
    }

    init(num: Int, den: Int) {
        _num = num
        _den = den 
    }
    /**
    加法函数
    - parameter other: 传入的另外一个Fraction类型的参数
    - returns: 返回的是一个数值
    */
    func add(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._den + other._num * _den, den: _den * other._den).simplify(). normalize()
    }

    func sub(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._den - other._num * _den, den: _den * other._den).simplify(). normalize()
    }

    func mul(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._num, den: _den * other._den).simplify(). normalize()
    }

    func div(other: Fraction) -> Fraction {
        return Fraction(num: _num * other._den, den: _den * other._num).simplify(). normalize()
    }

    func normalize() -> Fraction { //符号正规化函数
        if _den < 0 {
            _num = -_num
            _den = -_den
        }
        return self
    }

    func simplify() -> Fraction { //化简函数
        if _num == 0 {
            _den = 1
        }
        else {
            let x = abs(_num)
            let y = abs(_den)
            let g = gcd(x, y)
            _num /= g
            _den /= g
        }
        return self
    }
}


// 运算符重载(为自定义的类型定义运算符)

func +(one: Fraction, two: Fraction) -> Fraction {
    return one.add(two)
}

func -(one: Fraction, two: Fraction) -> Fraction {
    return one.sub(two)
}

func *(one: Fraction, two: Fraction) -> Fraction {
    return one.mul(two)
}

func /(one: Fraction, two: Fraction) -> Fraction {
    return one.div(two)
}


类的拓展2
知识点解释:
2.1 级联编程
  如上的四个函数,return的最后面的写法,先对分数进行化简,再把分数进行正规化显示。
2.2 运算符重载
  将函数名换成符号,重调上面的相对应的函数,而此时的参数就需要调用两个了

2.3 注释
  如上述的在(接下面)
/**

*/
之内的注释,将在你调用函数时显示名称,帮助代码阅读者理解,显示效果为:

屏幕快照 2016-08-13 10.30.45.png

类的拓展3
知识点:
  3.1.继承:从已有的类创建新类的过程。其中提供继承信息的称为父类(超类/基类),得到继承信息的称为子类(派生类/衍生类)。通常子类除了得到父类的继承信息还会增加一些自己特有的东西,所以子类的能力一定比父类更强大。
  继承的意义在于子类可以复用父类的代码并且增强系统现有的功能

//创建一个宠物类:包含阿猫阿狗等小动物
//所以在这里就需要理清 —— 宠物是一个大类,即父类;
//阿猫阿狗等小动物是子类。子类继承父类的信息。
//因而,最初就应该创建一个包含了具有相同属性的父类——宠物类。
//代码演示如下:
enum Gender { //这是一个枚举类型来定义性别,之后可直接调用
    case Male
    case Female
}

class Pet {
    var nickname: String
    var gender: Gender
    var age: Int
    
    init(nickname: String, gender: Gender, age: Int) {
        self.nickname = nickname
        self.gender = gender
        self.age = age
    }
    
    func eat() {
        print("\(nickname)正在吃东西.")
    }
    
    func play() {
        print("\(nickname)正在玩耍.")
    }
    
    func shout() {
        print("\(nickname)发出了叫声.")
    }
}
class Dog: Pet { //这里的阿狗继承了宠物类
    var isLarge: Bool //只写特有属性
    
    init(nickname: String, gender: Gender, age: Int, isLarge: Bool) {
        self.isLarge = isLarge //只初始化特有属性
        super.init(nickname: nickname, gender: gender, age: age)
        //super调用父类公用的属性    
}
    
    override func play() {  //重写玩这个属性,稍后做解释
        print("\(nickname)正在接飞碟.")
    }

    override func shout() {
        print("\(nickname): 汪汪汪……")
    }
    
    func keepTheDoor() {
        if isLarge {
            print("\(nickname)正在看门.")
        }
        else {
            print("\(nickname)太小了,你怎么忍心放它出来看门?!!!")
        }
    }
}

此时就已经建立好了一个父类(Pet)和一个子类(Dog),接下来我们来看一下他们之间的调用。

let dog = Dog(nickname: "大黄", gender: .Male, age: 1, isLarge: true)
dog.play()
//打印结果:大黄正在接飞碟

如上所示:dog为Dog类,在创建时,会继承父类的属性信息,如:姓名,性别等等......而方法的重写又可以使子类的实现不一样的“行为”,在子类又可以实现自己的特有属性和特殊“行为”。


3.2 多态:同样的对象类型(Pet类型)接收相同的消息(调用相同的方法),但是做了不同的事情,这就是多态(polymorphism)。

在简单的知道了多态之后,我们要如何创建一个多态呢?答案如下:

**实现多态的关键步骤: **
 ①. 方法重写(子类在继承父类的过程中对父类已有的方法进行重写, 而且不同的子类给出各自不同的实现版本)

ps: 父类有的方法子类可以重新实现,这个过程叫方法重写;
     需要在方法前添加override关键字;
     重写有时也被称为置换/覆盖/覆写。
     如上的继承讲解里出现的一样:

    override func play() {  //重写玩这个属性,在这里做了解释
        print("\(nickname)正在接飞碟.")
}

②. 对象造型(将子类对象当成父类型来使用)

    //如上的继承一致,再创建一个阿猫类:
    class Cat: Pet {
    var hairColor: String?
    
    // 父类有的方法子类可以重新实现 这个过程叫方法重写
    // 需要在方法前添加override关键字
    // 重写有时也被称为置换/覆盖/覆写
    
    override func play() {
        print("\(nickname)正在玩毛线球.")
    }
    
    override func shout() {
        print("\(nickname): 喵喵喵……")
    }
    
    func catchTheMouse() {
        print("\(nickname)正在抓老鼠.")
    }
}

所以在这里就有两个类——阿狗类和阿猫类继承了宠物类

let petsArray = [
    Cat(nickname: "加菲", gender: .Female, age: 2),
    Dog(nickname: "大黄", gender: .Male, age: 1, isLarge: false) ]

for pet in petsArray {
    pet.eat()
    pet.play()

    pet.shout()
    // 可以通过if+as?将父类型安全的转换成子类型然后再调用子类特有方法
    if let dog = pet as? Dog {
        dog.keepTheDoor()
    }
    else if let cat = pet as? Cat {
        cat.catchTheMouse()
    }
}

//打印结果:
          加菲正在吃东西.
          加菲正在玩毛线球.
          加菲: 喵喵喵……
          加菲正在抓老鼠.
          大黄正在吃东西.
          大黄正在接飞碟.
          大黄: 旺旺旺……
          大黄太小了,你怎么忍心放它出来看门?!!!

根据以上的打印结果的解释—— 加菲和大黄吃的东西都在调用的父类的eat()这个方法,玩耍、嚎叫和各自的看家本领都是自己重写函数后的新体现,这就是多态,不同的类调用相同的方法,在复写后,执行出了不同的效果


若此时出现了人类,人类就不能继承这个宠物类了,用脚想都不会继承,也没有谁愿意继承。而人就是一个单独的、平行的类。
人类要领养动物时候,传入的参数则是宠物类,而不是阿猫阿狗类,详见代码:

class Person {
    var name: String
    var pet: Pet?       // Person和Pet之间是HAS-A(关联)
    
    init(name: String) {
        self.name = name
    }
    func adopt(pet: Pet) {
        print("\(name)领养了\(pet.nickname).")
        self.pet = pet
    }
    func play() {
        if let pet = pet {
            print("\(name)正在和\(pet.nickname)玩耍.")
        }
        else {
            print("\(name)正在吃手!")
        }
    }
}
let person = Person(name: "Xyk_")
let dog = Dog(nickname: "二黄", gender: .Male, age: 1, isLarge: true)
person.adopt(dog)
person.play()
//打印结果:
          王大锤领养了二黄.
          王大锤正在和二黄玩耍.

今天没有心灵鸡汤。
张嘉佳说:“云和海分居两地,人和人相聚别离。希望有一天听到你的消息,海醒过来,风吹过去,你正和花一起生活。我们互道再见,我们还会再见。”
                            ——写在最后

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

推荐阅读更多精彩内容

  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,643评论 0 11
  • 前言:最近感冒的不太想去面试,在家就对Java se的基础做了一些小总结 1.JDK和JRE的区别 一 基础知识 ...
    AntCode阅读 1,126评论 0 1
  • 继承和多态 1. 继承的优缺点 优点:(1)子类可以灵活地改变父类中的已有方法;(2)能够最大限度的实现代码重用。...
    MinoyJet阅读 625评论 0 0
  • 字典: 字典的定义 ~字典(存放键值对组合的容器)~字典中的每个元素都是由两部分构成的, 冒号前面是键冒号后面是值...
    selfenhancement阅读 242评论 0 2
  • 魏家村,原不叫这名,是那魏府的魏老爷给村上带来了富裕,故为感恩他所改的,以示他在村民心中的地位。魏府,祖上是京城的...
    兵晓天澜阅读 434评论 0 2