Swift第三周学习心得
第三周主要学习了关于以下几种知识
一、数组的三种重要方法
关于数组的运用有三种重要的方法
1.过滤 (留下满足要求的)
let array = [23, 37, 96, 55, 40, 92, 68, 88]
let newArray = array.filter { (n : Int) -> Bool in
return n > 50
}
print(newArray)
let newArray2 = array.filter { (n) -> Bool in
return n % 2 == 0
}
print(newArray2)
关键字-filter
2.映射 (对原来的数组进行你给的要求的变化变成新的数组)
let array = [23, 37, 96, 55, 40, 92, 68, 88]
let newArray3 = array.map { (n : Int) -> Int in
return n * n
}
print(newArray3)
关键字-map
3.缩减(规约)
let result1 = array.reduce(0, combine: +) //初始值 缩减(规约)的方法
let result2 = array.reduce(0, combine: *)
let result3 = array[1..<array.count].reduce(array[0]) { $1 > $0 ? $1 : $0 }
print(result3)
关键字-reduce
二、闭包
如果函数的最后一个参数是闭包可以写成尾随闭包的形式
也就是将闭包放到函数参数的圆括号外面写在一对花括号中
如果函数后面有尾随闭包且函数的圆括号中没有参数
那么函数的圆括号也可以省略(仅限于有尾随闭包的场景)
闭包函数有很多种省略的方法
var array = ["game", "abacus", "hello", "cat", "good", "internationalization", "chaos", "dislike", "zealot", "young"]
array.sortInPlace {
if $0.characters.count == $1.characters.count {
return $0 < $1
}
return $0.characters.count < $1.characters.count
}
print(array)
三、集合
集合与数组一样都是存放数据的方式,但不同的是集合内存放的元素是不能重复的,并且他们的存储也不是按顺序存储的,反而是通过哈希计算随机存储
var b : Set<Int> = [1, 2, 3, 1, 2, 5] //集合
var c : Set<Int> = [3, 5, 7, 9, 11]
print(b)
print(b.intersect(c)) //交集 b和c都有的
print(b.union(c)) //并集 b和c所有的
print(b.subtract(c)) //差集 b有c没有
遍历集合
for x in b{
print(x)
}
b.insert(6) //添加元素
b.remove(2) //删除元素
四、字典
字典是存放键值对组合的容器
字典中的每个元素都是由两个部分构成,冒号前面是键,后面是值
var dict = ["abacus": "算盘", "abnormal": "异常", "hello": "你好", "good": "很好"]
//key --> value
//通过键值获取对应值(可空类型,因为给的键有可能没有与之对应的值)
print(dict["hello"]) //]后加感叹号,如果找不到值,程序就出错。
//添加元素
dict["shite"] = "嘟嘟"
//删除元素
dict.removeValueForKey("hello") // or dict["hello"] = nil
//修改值就重新赋值
dict["good"] = "不好"
//遍历一个字典
//遍历字典中所有的值
for value in dict.values{
print(value)
}
//遍历字典中所有的键
for key in dict.keys{
print("\(key) ---> \(dict[key])")
}
//最常用,通过元组获得字典中的键和值。
for (key, value) in dict{
print("\(key) ---> \(value)")
}
五、函数
定义一个函数
func 函数名(参数列表) -> 返回类型{函数执行体}
可以给函数的参数设定默认值,如果调用函数的时候没有给该参数赋值就直接使用默认值
func sayhello(personName : String, _ alreadyHello : Bool = false) ->String{ // 可以加默认值
//let hello = "hello, " + personName + "!"
//如果函数的返回类型不是void,那么函数中一定有return语句
//return "hello, " + personName + "!"
//return hello
if alreadyHello{
return "又是你" + personName + "!"
}
else {
return "hello" + personName
}
}
调用函数,直接写函数名字传参数 -- 函数名(参数组)
调用Swit的函数时,在默认情况下从第二个参数开始需要写参数名
print(sayhello("qqq", true))
//没给第二个参数赋值,直接使用默认你。再写上参数和默认值一样的也可以
print(sayhello("qq"))
//let str = sayhello("qq")
//print(str)
函数的参数名
函数名(外部参数名 内部参数名 : 类型, 外部参数名 内部参数名 : 类型)
如果不写外部参数名,那么内部参数名也就是外部参数名
可以用_来作为外部参数名表示省略外部参数名
func myMin(x : Int, _ y : Int) -> Int{ // 调用不想写y 就在y前面写 _ y 省略外部参数名
return x < y ? x : y
}
//调用函数写外部参数名
print(myMin(3, 5))
函数的参数列表是可变的,称可变参数列表,函数参数个数是任意个
func sum1(nums: Int...) -> Int{
var total = 0
for num in nums{
total += num
}
return total
}
print(sum1())
print(sum(1,2,3))
print(sum1(11,12,12,23,44,56))
六、类
1.定义类(如果你要用的类苹果已经提供了就直接进入第2步)
0.发现类
- 在对问题的描述里面找名次和动词
- 名词会成为类或者类中的属性,动词会成为类中的方法
1.定义类
- 数据抽象(属性)
- 行为抽象(方法)
- 初始化方法
访问修饰符
- public(公开,别的项目也能用)
- interna(内部的) - 默认
- private(私有,外界不让访问)
- 修饰符可以加在类,属性,方法前面,但公开只能先公开类,再公开别的
定义类就可以创建出新的类型
学生类
class Student {
// 变量定义到类的外面就叫变量 - variable
// 变量定义到类的里面就叫属性 - property
// 数据抽象 - 找到和学生相关的属性(找名词)
var name: String
var age: Int
// 初始化方法(构造方法/构造器) - constructor
init(name: String, age: Int) {
self.name = name
self.age = age
}
// 函数写到类的外面就叫函数 - function
// 函数写到类的里面就叫方法 - method
// 行为抽象 - 找到和学生相关的方法(找动词)
func eat() {
print("\(name)正在吃饭.")
}
func study(courseName: String) {
print("\(name)正在学习\(courseName).")
}
func watchJapaneseAV() {
if age >= 18 {
print("\(name)正在观看岛国爱情动作片.")
}
else {
print("亲爱的\(name), 我们推荐你观看《熊出没》")
}
}
}
步骤2: 创建对象(调用初始化方法)
let stu1 = Student(name: "骆昊", age: 35)
步骤3: 给对象发消息(通过给对象发消息来解决问题)
stu1.eat()
stu1.study("Swift程序设计")
stu1.watchJapaneseAV()
let stu2 = Student(name: "王大锤", age: 15)
stu2.eat()
stu2.study("中国近代史")
stu2.watchJapaneseAV()
类是面对对象编程很重要的部分。在我的理解中,面对对象编程的对象就是通过类具体化得到的。我们说的类事包含很多属性方法的抽象的一个合集,我们从中具体化(创建)一个对象出来对它发消息,消息的内容就是我们希望对象完成的事。
2.创建一个类基本上要经过三个步骤
数据抽象-初始化所有存储属性-行为抽象
class Robot {
// 数据抽象
var answer : Int // 正确答案
var counter : Int // 猜的次数
var hint : String // 提示信息
//对所有存储属性都要初始化(有初始值,默认值)
init(){
answer = Int(arc4random_uniform(100)) + 1
counter = 0
hint = ""
}
// 行为抽象
// 判断
func judge(qqq : Int) -> Bool{
counter += 1
if qqq < answer{
hint = "大一点"
}
else if qqq > answer{
hint = "小一点"
}
else{
hint = "恭喜你猜对了!你总共猜了\(counter)次"
return true
}
return false
}
}
swift里把得到某个值的方法就用名次做方法名,但也能写成如下
通常获得某个计算出来的值的方法都可以设计成计算属性
计算属性(通过对存储属性做运算得到的属性)
3.类的扩展
类的扩展也是很重要的一个部分
扩展,不要改原来的类,神噩梦时候用就在用的地方扩展
如果在某个特定的应用场景中你发现现有的类缺少了某项功能
那么可以通过类的扩展(extension)的方式现场添加这项功能
关键字 extension 类名
extension Point{
var cgPoint: CGPoint{
get {
return CGPointMake(CGFloat(x), CGFloat(y))
}
}
}
class Triangle {
var va: Point
var vb: Point
var vc: Point
var color : UIColor?
init(va : Point, vb: Point, vc: Point){
self.va = va
self.vb = vb
self.vc = vc
}
var perimeter: Double{
get{
let ab = va.distentsTo(vb)
let bc = vb.distentsTo(vc)
let ac = vc.distentsTo(va)
return ab + bc + ac
}
}
var area: Double{
get{
let ab = va.distentsTo(vb)
let bc = vb.distentsTo(vc)
let ac = vc.distentsTo(va)
let halfp = perimeter / 2
return sqrt(halfp * (halfp - ab) * (halfp - bc) * (halfp - ac))
}
}
func draw(){
let bezierPath = UIBezierPath()
bezierPath.moveToPoint(va.cgPoint)
bezierPath.addLineToPoint(vb.cgPoint)
bezierPath.addLineToPoint(vc.cgPoint)
bezierPath.addLineToPoint(va.cgPoint)
//color?.set()
// if let color = color{
// color.set()
// }
// else{
// UIColor.blueColor().set()
// }
//let nowcolor = color == nil ? UIColor.blueColor() : color!
//如果为空用??后面的值,不为空就直接用??前面的值,也就是它本身的值
let currentColor = color ?? UIColor.blueColor()
currentColor.set()
// 上面写法的升级版
//(color ?? UIColor.blueColor()).set()
bezierPath.stroke()
}
}
4.类的继承
从已有的类创建出新类的过程
提供继承信息的类称为父类(超类/基类)
得到继承信息的类称为子类(派生类/衍生类)
通常子类除了得到父类的继承信息还会增加一些自己特有的东西
所以子类的能力一定比父类更强大
继承的意义在于子类可以复用父类的代码并且增强系统现有的功能、
class Student: 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("\(name)是\(gender == .Male ? "男" : "女")")
print("\(name)正在学\(courseName)")
}
}
我们可以将子类型的对象赋值给父类型的变量(因为子类跟父类之间时is-a关系)
学生是人,老师是人,所以学生和老师的对象可以赋值给人类型的变量
如果要将父类型的变量转换为子类型需要使用as运算符进行类型转换
如果能够确认父类型的变量中就是某子类型的对象可以用as!进行转换
如果不能确定父类型的变量中时那种子类型可以用as?尝试转换
let p2: Person = Student(name: "klle", age: 21, gender: .Female, major: "计算机")
p2.eat()
(p2 as! Student).study("社会学")
if let tmp = p2 as? Teacher{
tmp.teach("Java")
}
else{
print("\(p2.name)不是老师!")
}
let p3 = Teacher(name: "ollp", age: 35, gender: .Male, title: "渣渣")
p3.eat()
p3.teach("补到")
注意
if let tmp = p2 as? Teacher
p2是Person类,我们定义一个tmp代表P2,尝试将其转换成tercher类,用If- As?的方法,如果能转,tmp就能调用teacher类的方法那些,不能转换也不影响