swift封装,继承,多态,代理,委托

语言基础

程序是指令的集合,写程序就是写一系列的指令去控制计算做我们想做的事情
编译:将程序设计语言转换成计算机能够理解的机器语言或者某种中间代码的过程

冯诺依曼体系结构的计算机
1.使用二进制
2.程序存储执行

变量和常量

定义变量和常量是为了保存数据,变量和常量就是某种类型值得存储空间。

var a:Int = 10
a = 100
var b : Int
b = 1000
var c = 1000

let d :Int = 10
//d = 100 //complier error
let e = 1000
let e = 1000

说明:1.Swift有非常强大的类型推断,所以定义变量或者常量时如果可以的话应该直接使用类型推断不用手动指定类型;2.如果可以的话应该竟可能使用常量而不是变量

语言元素

var a : Int = 10

关键字:有特殊含义的单词
标识符:给变量、常量、函数、类型、协议、枚举、方法、属性等起的名字

命名规则
1.字母(Unicode字符)、数字、下划线,数字不能开头
2.大小写敏感(区分大小写)
3.不能使用关键字做标识符
4.使用驼峰命名法(命名变量、常量、函数、方法、属性第一个单词小写,从第二个单词开始每个单词首字母大写:命名类、结构、协议、枚举每个单词首字母都要大写)
5.见名知意
6.命名私有的属性和方法时以下划线开头

运算符:Swift中的运算符其实是函数

1.赋值运算符:=、+=、-=、...
2.算术运算符:+、—、*、/、%
3.比较运算符:==、!=、<、<=、>、>=
4.逻辑运算符:&&、||、!
5.条件运算符:..?..:..
6.其他运算符:[ ]、.、??、?、!

字面(常)量:

1.整数字面量:10、1_234_567、0x10、0o10、0b10
2.小数字面量:123.45、1.2345e2、0xab.cdp2
3.字符字面量:"c"、"\n"、"\u(41)"、"\u{9a86}"
4.字符串字面量:"Hello"、"caf\u{e9}"
5.布尔字面量:true、false
6.可空字面量: nil
7.类型字面量:String.self、ULLabel.self

分隔符:将不同的语言元素符号分开

说明:Swift中每个语句后面的分号是可写可不写的,写代码时时尽量保证一行只有一个语句这样就可以省略分号。

分支和循环

分支if -else

//判断闰年
let year = 1980
if year%4==0&&year!=100||year%400==0{
  print{"是闰年"}
}else{
  print{"不是闰年"}
}
//分段函数
let x = 3.2
let y :Double
if x < -1 {
y=3*x-5
}else if x>3{
y=4*x+10
}else{
y=5
}

switch {case n:;default:}

let score = 60
let lv: String
switch score {
    case 0..<20:lv = "新手"
    case 20..<40:lv = "中级"
    case 40..<60:lv = "高级"
    default:lv = "大神"
   }
   print(lv)

循环求和:
1.直到型循环
repeat{ }while

var i = 1
var sum = 0
repeat{
sum += i
  i += 1
}while i<=100

2.当型循环while{ }

var i = 1
var sum = 0
while i<=100{
  sum += i
  i += 1
}

3.for循环for i in 1...n { }

var sum = 0
for i in 1...100{
  sum += i
}

穷举法:穷尽所有可能性直到能找到正确答案
"百钱百鸡"问题:
5元一公鸡;3元一母鸡;一元3小鸡;

for x in 0...20{
    for y in 0...33{
        let z= 100-x-y
        if 5*x+3*y+z/3==100&&z%3==0{
        print("公鸡\(x)只,母鸡\(y)只,小鸡\(z)只")
        }
    }
}

说明:在循环中可以使用break关键字来提前终止循环,也可以使用continue关键字使循环直接进入下一轮,但是应该尽可能减少对break和continue的使用,因为他们不会让你的程序变得更好。

综合案列:Craps赌博游戏.

游戏规则:玩家摇两颗骰子,如果第一次摇到11或7,玩家胜;如果摇出2点,3或12,则庄家胜;其他点数继续,如果摇出7点,庄家胜,摇出玩家第一次的点数,玩家胜,其他继续

func roll()->Int{
return Int(arc4random_uniform(6)+1)
}
let thyPoint = roll() + roll()
print("玩家摇出了\(thyPoint)点")
var needsGoOn = false
switch thyPoint {
case 7,11:print("玩家胜")
case 2,3,12:print("庄家胜")
default:
    needsGoOn = true
}
while needsGoOn {
let currentPoint = roll()+roll()
print("玩家摇出了\(thyPoint)点")
    if currentPoint == thyPoint {
        print("玩家胜")
        needsGoOn = false
    }else if currentPoint == 7{
        print("庄家胜")
        needsGoOn = false
    }
}

容器

数组

  • 创建数组
let array1:[Int] = []
//let array1:Array<Int> = [] //等效
let array2 = [1,2,3,4,5,6]
let array3 = [Int](count:5,repeatedValue:0)
let array5 = Array<Int>(count:5,repeatedValue:0)
  • 添加元素
array1.append(2)
array1.append(3)
array1.insert(1,atIndex:0)
array1.insert(4,atIndex:array1.count)
array1 += [5]
array1 += [6.7.8]
  • 删除元素
array1.removeAtIndex(2)
array1.removeFirst()
array1.removeFirst(2)
array1.removeLast()
array1.removeRange(1...2)
array1.removeAll()
  • 修改元素
array3[0] = 100
array3[array3.count-1] = 500
print(array3)
  • 遍历数组

1.方式1

for i in 0...array.count {
    print(array[i])
}

2.方式2

for temp in array3 {
    print(temp)
}

for temp in array3[1...3]{
    print(temp)
}

说明:for-in循环是一个只读循环,这也意味着在循环过程中不能进行修改
3.方式3

for (i,temp) in array3.enumerate(){
    if i == 1{
    array3[i] = 1}
    print("\(i).\(temp)")
}

提醒:操作数据时最重要的是不要越界访问元素。数组对象的count属性表明了数组有多少个元素,那么有效的索引(下标)范围0到count-1

数组中的元素也可以是数组,因此我们可以构造多维数组。最常见的是二维数组,它相当于是一个有行有列的数组,数组中的每个元素代表一行,该数组中的每个元素代表行里面的列。二维数组可以模拟显示世界中的表格、数学上的矩阵、棋类游戏棋盘、格子类(2d)游戏的地图。所以在实际开发中使用非常广泛。

//二维数组
func randomInt(min:UInt32,max:UInt32)->Int{
    return Int(arc4random_uniform(max-min+1)+min)
}
let nameArray = ["关羽","张飞","赵云","马超","黄忠"]
let coursesArray = ["语文","数学","英语"]
var scoresArray3 = [[Double]](count:nameArray.count, repeatedValue: [Double](count:coursesArray.count, repeatedValue: 0))

for i in 0..<scoresArray3.count{
    for j in 0..<scoresArray3[i].count{
        scoresArray3[i][j] = Double(randomInt(0,max:100))
    }
}

for (index,array) in scoresArray3.enumerate(){
    var sum = 0.0
    for score in array{
        sum += score
    }
    let avg = sum / Double(coursesArray.count)
    print("\(nameArray[index])的平均成绩为:\(avg)")
}
for i in 0..<coursesArray.count{
    var sum = 0.0
    for row in 0..<scoresArray3.count{
        sum += scoresArray3[row][i]
    }
    let avg = sum / Double(nameArray.count)
    print("\(coursesArray[i])的平均成绩为:\(avg)")
}

集合

集合在内存中是离散的,集合中的元素通过计算Hash Code(哈希码或散列码)来决定放在内存中的什么位置,集合中不允许有重复元素。

  • 创建集合
var set:Set<Int>=[1,2,3,4,5,1]
  • 添加元素
set.insert(100)
  • 删除元素
set.remove(x)
//删除哈希码第一个
set.removeFirst()
set.removeAll()
  • 集合的遍历
for smap in set{
    print(temp)
}
  • 交集,并集,差集
var set1:Set<Int> = [1,3,5,7,8,4,9]
var set2:Set<Int> = [1,3,5,6]

set1.intersect(set2)//交
set1.union(set2)//并
set1.subtract(set2)//差

字典

字典是以键值对的方式保存数据的容器,字典中的元素是键值对的组合,通过键可以找到对应的值。

-创建字典

var dict = [
1:"hello",
2:"good",
3:"wonderful",
5:"delicious"
]
  • 添加元素和删除元素,修改元素
dict[4] = "great"
dict.count
dict
dict[5] = nil//删除直接赋空
//dict.removeValueForKey(5)过于复杂
dict[1] = "abc"//修改
  • 遍历字典
for key in dict.keys {
    print("\(key)--->\(dict[key]!)")
}

for value in dict.values {
    print(value)
}

for(index,value) in dict.enumerate(){
    print("\(index).\(value)--->\(value.1)")
}

重要操作

  • 排序
    1.sort
    2.sortInPlace

说明:排序方法的参数是一个闭包(closure)该闭包的作用是比较数组中两个元素的大小

let array=[23,54,12,45,69,7]
array.sort({(one:Int,two:Int)->Bool in return one<two})
array.sort({(one,two)in one < two})
array.sort({one ,two in one < two})
array.sort({$0 < $1})
array.sort{$0<$1}
array.sort{<}
  • 过滤
let array=[23,54,12,45,69,7]
let newArray = array.filter{$0>50}
print(newArray)
  • 映射
//通过映射对数据进行变换处理
let array=[23,54,12,45,69,7]
let newArray = array.map{$0*$0}
print(newArray)
let newArray2 = array.mao{sqrt(Double($0))}
print(newArray2)

  • 规约
let array=[23,54,12,45,69,7]
let newArray = array.filter{$0>50}
let newArray1 = newArray.map{$0*$0}
let result = newArray.reduce(0,combine:+)
print(result)

函数和闭包

函数是独立的可重复使用的功能模块,如果程序中出现了大量的重复代码,通常都可以将这部分功能封装成一个独立的函数。在Swift中,函数是"一等公民"函数作为类型来使用,也就是说函数可以赋值给一个变量或常量,可以将函数作为函数的参数或者返回值,还可以使用高阶函数。

func 函数名([参数1:类型,参数2:类型,...])[throw|rethrows]->返回类型{
    函数执行体
    [return 表达式]
}
  • 外部参数名

  • inout参数

  • 可变参数列表

闭包就是没有名字的函数或者称之为函数表达式(Lambda表达式),Objective-c中与之对应的概念叫block.如果一个函数的参数类型是函数,我们可以传入一个闭包,如果一个函数的返回类型是函数我们可以返回一个闭包。如果一个类的某个属性是函数我们也可以将一个闭包表达式赋值给它。

{([参数列表]) [->返回类型]in 代码}

面向对象编程(oop)

基本概念

对象:接受消息的单元。(对象是一个具体的概念)

类:对象的蓝图和模块,类是一个抽象概念。

消息:对象之间通信的方式,通过给对象发消息可以让对象执行对应的操作来解决问题

四大支柱

抽象:定义类的过程就是一个抽象过程,需要做数据抽象和行为抽象,数据抽象找到对象的属性(保存对象状态的存储属性),行为抽象找到对象的方法(可以给对象发消息)

封装:

  • 观点1:我们在类中写方法其实就是在封装API,方法的内部实现可能会很复杂,但是这些对调用者是不可用的,调用者只能看见方法有一个简单清晰的接口,这就是封装。
  • 观点2:将对象的属性和操作这些属性的方法绑定在一起。
  • 观点3:隐藏一切可以隐藏的实现细节,只提供简单清晰的接口(界面)。

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

多态:重写
重载 - overload 子类将父类已有的方法重写实现一边
重写 - override

3个步骤

1.定义类

  • 数据抽象
    • 存储属性
  • 行为抽象
    • 方法(写到类里面的函数就是方法)
      • 对象方法:给对象发消息,先创建对象再调用
      • 类方法:给类发的消息,与对象的状态无关的方法(例如,三角形提前判断是否能构成三角形),直接在类上打点,调用。在方法前加STATIC或者class也可以
    • 计算属性
  • 构造器
    • 指派构造器
    • 便利构造器(convenience)
    • 必要构造器 (required)
      2.创建对象
      3.给对象发消息
class 

相关内容

  • 枚举
  • 结构(体)

总结类和结构的区别到底有哪些?什么时候使用结构?什么时候该使用类?

  • 扩展(extension)
  • 运算符重载,要写在类外
  • 下标运算(subscript)
  • 访问修饰符
    • Private
    • internal
    • public

面向协议编程(pop)

协议

protocol 协议名[:父协议1,父协议2,...]{
    // 方法的集合(计算属性相当于方法)
}

1.能力
2.约定
3.角色

依赖倒转原则

设计模式

  • 代理回调
  • 委托回调
  • 一个对象想做某件事但是自身没有能力做这件事情就可以使用委托回调,集体步骤是:
    • 1.设计一个协议,让被委托方遵循协议并实现协议中的放法
    • 2.委托方有一个属性是协议类型的,通过该属性可以调用协议中的方法
    • 委托方的协议类型的属性通常是可空类型,因次要写成weak引用

其他

  • 协议组合:protocal<协议1,协议2,...>
  • 可选方法
  • 协议拓展

泛型

让类型不再是程序中的硬代码(hard code),可以设计出更通用的代码

  • 泛型函数

  • 泛型类/结构/枚举

相关知识

  • 泛型限定
  • where子句

错误处理

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

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,865评论 6 13
  • ☻今日心晴☻ 昨晚听到荣荣妈家的娃娃病了,瞬间感受到当妈的焦虑,心急,无奈。回想起以前的荣荣,似乎变了好多,可仔细...
    sunny段晓阅读 117评论 0 0
  • ❤️❤️玻尿酸 这根本不算新品了 老顾客都知道我家的玻尿酸 因为原料缺乏 所以断货了一段时间 现在又重新以可爱的模...
    LLstudio阅读 272评论 0 0