Swift第2周学习总结

[TOC]

字典集合

字典:字典(存放键值对组合的容器)字典中的每个元素都是由两部分构成的, 冒号前面是键冒号后面是值
集合:Swift中的Set类型被写为Set<T>,这里的T表示Set中允许存储的类型。

var dict: [String: String] = ["a": "你", "b": "好"]

 通过键获取对应的值(可空类型, 因为给的键有可能没有与之对应的值)
print(dict["hello"]!)// key ---> value
print(dict["abcxyz"])

元素的添加修改删除


dict["c"] = "吗"// 添加元素

dict.removeValueForKey("hello")// 删除元素
dict["hello"] = nil //删除元素的值

dict["c"] = "你好" //元素值的修改

遍历


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


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


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

集合的创建

var a: Set<Int> = [1, 2, 3, 4, 2, 5]

集合元素的修改

a.insert(100)           // 添加元素
a.remove(2)             // 删除元素

集合的操作

var b: Set<Int> = [3, 5, 7, 9, 11]
var a: Set<Int> = [1, 2, 3, 4, 2, 5]
print(a.intersect(b))   // 交集(a和b都有的元素)
print(a.union(b))       // 并集(a和b的所有元素)
print(a.subtract(b))    // 差集(a有b没有的元素)
let c: Set<Int> = [1, 3]
print(c.isSubsetOf(a))      // 判断c是不是a的子集
print(a.isSupersetOf(c))    // 判断a是不是c的超集

let d: Set<Int> = [2, 1000, 10000]
print(a.isDisjointWith(d))  // 判断两个集合是否相交

函数

定义函数:func 函数名(参数列表) -> 返回类型 { 函数的执行体 }
Swift中函数的参数可以设定默认值 如果调用函数的时候没有给该参数赋值就直接使用默认值

func sayHello(personName: String, alreadyGreeted: Bool = false) -> String {//Bool 默认值是false ->返回的类型
    if alreadyGreeted { 
           return "你好, " + personName + "!"
    }

函数的参数名:函数名(外部参数名 内部参数名: 类型, 外部参数名 内部参数名: 类型)
如果不写外部参数名那么内部参数名也是外部参数名
可以使用_来作为外部参数名表示省略外部参数名

func myMin(a x: Int, b y: Int) -> Int {//a,b外部参数名  x,y内部参数名
    return x < y ? x : y
}

调用函数的时候要写函数的外部参数名

print(myMin(a: 3, b: 5))

调用函数: 函数名(参数值), 调用Swift的函数时, 在默认情况下从第二个参数开始需要写参数名

print(sayHello("小明", alreadyGreeted: true))

如果没有给第二个参数赋值那么就直接使用默认值false

print(sayHello("Jack")

Swift中函数的参数列表可以是可变参数列表(参数的个数是任意多个)

func sum(nums: Int...) -> Int {
    var total = 0
    for num in nums {
        total += num
    }
    return total
}
print(sum())
print(sum(999))
print(sum(1, 2, 3))
print(sum(90, 82, 37, 68, 55, 11, 99))

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

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 sum
}

闭包

闭包:闭包是功能性自包含模块,可以在代码中被传递和使用
传入匿名函数(闭包)
如果函数的最后一个参数是闭包可以写成尾随闭包的形式
也就是将闭包放到函数参数的圆括号外面写在一对花括号中
如果函数后面有尾随闭包且函数的圆括号中没有参数
那么函数的圆括号也可以省略(仅限于有尾随闭包的场景)
1.1 完整的闭包写法

print(foo(a, fn: { (a, b) -> Int in
   return a + b
}))

1.2 省略掉类型和不必要的括号

print(foo(a, fn: { a, b in a + b }))

1.3 省略参数名

print(foo(a, fn: { $0 + $1 }))

1.4 尾随闭包

print(foo(a) { (a, b) -> Int in
    return a + b
})


发现类

  • 在对问题的描述中找名词和动词
  • 名词会成为类或者类中的属性 动词会成为类中的方法

定义类

  • 数据抽象(属性)
  • 行为抽象(方法)
  • 初始化方法

访问修饰符
public (公开)
internal (内部的) - 默认
private (私有)
存储属性通常是private的 因为数据要保护起来
方法一般是public的 因为方法是对象接受的消息
如果自定义的类没有打算在其他项目中使用 可以不写访问修饰符
直接使用默认的internal修饰符表示在本项目中公开对其他项目私有


class Circle {
    // stored property
    // 存储属性(保存和圆相关的数据的属性)
    var center: Point
    var radius: Double
    
    init(center: Point, radius: Double) {
        self.center = center
        self.radius = radius
    }
    
    // 通常获得某个计算出的值的方法都可以设计成计算属性
    // computational property
    // 计算属性(通过对存储属性做运算得到的属性)
    var perimeter: Double {
        // 圆的周长是一个只读属性
        // 所以此处只有get{}没有set{}
        get { return 2 * M_PI * radius }
    }
    
    var area: Double {
        get { return M_PI * radius * radius }
    }
}

步骤1: 定义类(如果你要用的类苹果已经提供了就直接进入第2步)
定义类就可以创建出新的类型
例:学生类

class Student {
   // 变量定义到类的外面就叫变量 - variable
   // 变量定义到类的里面就叫属性 - property
   // 数据抽象 - 找到和学生相关的属性(找名词)
   var name: String
  var age: Int

  // 初始化方法(构造方法/构造器) - constructor
   init(name: String, age: Int) {
      self.name = name
      self.age = age
   }
       // 我们可以在一个类中定义多个初始化方法

   // 便利初始化方法 / 便利构造器
   // 调用了其他的初始化方法的初始化方法

   convenience init(s:(String,Int)) {
       self.init(name: s.0, age: s.1)
   }

   convenience init() {
       self.init(name: s.0, age: s.1)
   }

   // 指派初始化方法 / 指派构造器
   // 被其他初始化方法调用的初始化方法
   init(x: Double, y: Double) {
       self.x = x
       self.y = y
   }

   // 函数写到类的外面就叫函数 - function
   // 函数写到类的里面就叫方法 - method
   // 行为抽象 - 找到和学生相关的方法(找动词)

  func study(courseName: String) {
       print("\\(name)正在学习\\(courseName).")    }

   }
}

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

let stu1 = Student(name: "小明", age: 35)

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

tu1.study("Swift程序设计")

短除法(欧几里得算法)

x和y的最大公约数跟y%x和x的最大公约数是一样的
Greatest Common Divisor

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
    }
}

继承

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

创建父类

enum Gender { //枚举
    case Male
    case Female
}

class Person {
    var name: String
    var age: Int
    var gender: Gender
    
    init(name: String, age: Int, gender: Gender) {
        self.name = name
        self.age = age
        self.gender = gender
    }
    
    func eat() {
        print("\\(name)正在吃饭.")
    }
}

创建子类

class Student: Person {//:Person 继承人类(父类)
    var major: String//课程

    init(name: String, age: Int, gender: Gender, major: String) {
        self.major = major
        super.init(name: name, age: age, gender: gender)
    }

    func study(courseName: String) { //学生学习的方法
        print("\\(name)是\\(major)专业的学生.")
        print("\\(gender == .Male ? "他" : "她")正在学习\\(courseName).")
    }
}

创建对象

let per = Person(name: "小明", age: 25, gender: .Male)//创建小明
p1.eat()

可以将子类型的对象赋值给父类型的变量(因为子类跟父类之间是IS-A关系)
学生是人, 老师是人, 所以学生和老师的对象可以赋值给人类型的变量

let student: Person = Student(name: "张三", age: 18, gender: .Female, major: "计算机科学与技术")//创建学生张三
student.eat()//继承父类吃饭的方法

如果要将父类型的变量转换成子类型需要用as运算符进行类型转换
如果能够确认父类型的变量中就是某种子类型的对象可以用as!进行转换
如果不确定父类型的变量中是哪种子类型可以用as?尝试转换

(p2 as! Student).study("Swift程序设计")
if let temp = p2 as? Teacher {
    temp.teach("Java")
}
else {
    print("\\(p2.name)不是老师!!!")
}

面向对象

终极原则: 高内聚, 低耦合
面向对象七原则:

  1. 单一职责原则(SRP)
  2. 开闭原则(OCP)
  3. 依赖倒转原则(面向抽象编程, DIP)
  4. 里氏替换原则(LSP) - 能用父类型的地方就一定可以使用子类型
  5. 接口隔离原则(ISP)
  6. 合成聚合复用原则(CARP)
  7. 迪米特法则(LoD

GoF设计模式 - 23种设计模式

多态

同样的对象类型(Pet类型)接收相同的消息(调用相同的方法)
但是做了不同的事情 这就是多态(polymorphism)
实现多态的关键步骤:
1.方法重写(子类在继承父类的过程中对父类已有的方法进行重写, 而且不同的子类给出各自不同的实现版本)
2.对象造型(将子类对象当成父类型来使用)
可以通过if+as?将父类型安全的转换成子类型然后再调用子类特有方法
例 首先创建动物父类

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 play() {
        print("\\(nickname)正在玩耍.")
    }

    func shout() {
        print("\\(nickname)发出了叫声.")
    }
}


创建子类 猫

// Cat和Pet之间是IS-A关系(继承)
class Cat: Pet {
    var hairColor: String?
    // 父类有的方法子类可以重新实现 这个过程叫方法重写
    // 需要在方法前添加override关键字
    // 重写有时也被称为置换/覆盖/覆写
    override func play() {
        print("\\(nickname)正在玩毛线球.")
    }
    override func shout() {
        print("\\(nickname): 喵喵喵……")
    }
}

创建子类 狗

class Dog: Pet {//继承动物类
    init(nickname: String, gender: Gender, age: Int) {
        super.init(nickname: nickname, gender: gender, age: age)
    }
    override func play() {//重写玩耍的方法
        print("\\(nickname)正在接飞碟.")
    }

    override func shout() {//重写叫的方法
        print("\\(nickname): 旺旺旺……")
    }
}

创建 猫,狗

let petsArray = [
  Cat(nickname: "加菲", gender: .Female, age: 2),
 Dog(nickname: "旺财", gender: .Male, age: 3, )
]

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

运行结果:

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

推荐阅读更多精彩内容