今天没有没有心灵砒霜。
那是因为独木舟曾说过——那一刻你的心里有场海啸,可你静静地,没让任何人知道......
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 注释
如上述的在(接下面)
/**
*/
之内的注释,将在你调用函数时显示名称,帮助代码阅读者理解,显示效果为:
类的拓展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()
//打印结果:
王大锤领养了二黄.
王大锤正在和二黄玩耍.
今天没有心灵鸡汤。
张嘉佳说:“云和海分居两地,人和人相聚别离。希望有一天听到你的消息,海醒过来,风吹过去,你正和花一起生活。我们互道再见,我们还会再见。”
——写在最后