Swift的第二周爬坑之路

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


Point 1:集合
//1.集合的创建
var a:Set = [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 = [2,3,12,24,3,2]
var b: Set = [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.. 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 注释
  如上述的在(接下面)
/**

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

Swift的第二周爬坑之路_第1张图片
屏幕快照 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()
//打印结果:
          王大锤领养了二黄.
          王大锤正在和二黄玩耍.

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

你可能感兴趣的:(Swift的第二周爬坑之路)