六、扩展协议
1.使用扩展(extension)扩展类型的属性
//扩展:就是向一个已有的类、结构体或枚举类型添加新的能力。扩展可以对一个类型添加新的功能,但是不能重写已有的功能。
//关键字:extension
extension Int //对计算型属性进行扩展
{
var double: Int
{
return self * 2
}
var triple: Int
{
return self * 3
}
var fourfold: Int
{
return self * 4
}
var half: Double
{
return Double(self) / 2.0
}
}
2.double
2.triple
2.fourfold
2.half
2.使用extension对方法进行扩展
struct Point //定义结构体
{
var x = 0.0
var y = 0.0
}
extension Point //对结构体进行扩展
{
//添加扩展方法
func distance(anotherPoint: Point) -> Double
{ //计算与另一个点之间的距离
let distanceX = anotherPoint.x - self.x
let distanceY = anotherPoint.y - self.y
return sqrt(distanceX * distanceX + distanceY * distanceY)
}
}
let startPoint = Point(x: 0.0, y: 0.0)
let endPoint = Point(x: 10.0, y: 10.0)
startPoint.distance(anotherPoint: endPoint)
3.使用协议(protocol)进行方法的声明
//协议规定了用来实现某个功能所需的方法和属性。协议能够被类、结构体等具体实现(或遵守)。
//协议定义了一个方法的蓝图,属性和其它适合特定任务或功能的要求。定义协议与定义类、结构体和枚举非常相似。
protocol Walking
{
func walk()
}
protocol Eating
{
func eat()
}
//协议可以遵守另一个协议,将需要遵守的协议名称放在当前协议名称的后方,之间使用冒号进行分隔。
protocol Fighting: Walking
{
func fight()
}
//该类遵循两个协议,类名和协议名称之间仍然使用冒号进行分隔,而协议名称之间则使用逗号进行分隔。
class Animal : Fighting, Eating
{
var name = "Bird"
var age = 1
var damage = 10
func fight()
{
print("Fighting very hard!")
}
func eat()
{
print("Happily eating!")
}
func walk()
{
print("Working gracefully!")
}
func say()
{
print("I'm a dove of peace!")
}
}
var animal = Animal()
animal.damage
animal.fight()
animal.eat()
animal.walk()
animal.say()
extension Animal //对类进行扩展
{
var weight: Double
{
get{return 15.0}
}
func getWeight()-> Double
{
return 45.6
}
}
var secondAnimal = Animal()
secondAnimal.say()
secondAnimal.getWeight()
4.问号?和感叹号!的用法解析
//系统不会自动给变量设置初始值,也就是说变量不会有默认值,所以在使用变量之前需要进行初始化。
//使用泛型定义一个Optional类型的变量,从右侧可以看出,它是空值nil,没有初始化值。Optional其实是个枚举,里面有None和Some两种类型,用来包装原始值。
//var password: Optional<Any>
//var password: String?
//var password: String
//print(password.characters.count)
//第一个问号:作用是声明一个Optional变量;第二个问号:作用是在对Optional值操作时,判断是否可以响应后面的操作。
//var password: String?
//print(password?.characters.count)
//双问号(??):当前面的代码无法执行时,就采用双问号后面的值
//var password: String?
//print(password?.characters.count ?? 0)
//感叹号(!):对Optional值进行拆包(从枚举里面取出来原始值)
//var password: String?
//print(password!.characters.count)
var password: String?
password = "123456"
//print(password!.characters.count)
print(password?.characters.count ?? 0)
//传统的空值判断,通常要使用if语句,代码量比较大,而使用问号和感叹号,则可以很简洁的进行空值判断。
class Pet
{
var name : String?
}
class Person
{
var name : String?
var pet : Pet?
}
let person = Person()
person.pet
person.pet?.name
person.pet = Pet()
person.pet
person.pet?.name
person.pet?.name = "Bird"
person.pet?.name
5.Swift中的闭包(Closure)详解
var sum:(Int,Int) ->Int = //等号下方的大括号:是用来实用一个函数功能的代码块
{
//两行代码:第一行代码:用来声明函数代码块的参数和返回值信息;第二行代码:对参数操作,放在in的下方
(a:Int, b:Int)->Int in
return a + b
}
sum(1, 1)
//和上方功能相同
func sum(a:Int, b:Int)->Int
{
return a + b
}
sum(1, 1)
//使用闭包声明一个函数类型的变量时,可以省略对变量类型的定义,系统会自动推断出它的类型
var anotherSum =
{
(a:Int, b:Int)->Int in
return a + b
}
//等号右侧,省略了参数声明的闭包语句
var thirdSum: (Int, Int) -> Int = {return $0 + $1}
thirdSum(1, 1)
//使用$0和$1表示第一个参数和第二个参数,并且省略了return操作符
var fourthSum: (Int, Int) -> Int = {$0 + $1}
fourthSum(1, 1)
let array = [4, 2, 3].sorted(){ $0 < $1 }
array
//闭包语句通常和方法声明配合使用,但是闭包语句通常放在最后一个参数的位置。
func subTowNumbers(number1: Int, number2: Int, method: (Int, Int) -> Int) -> Int
{
return method(number1, number2)
}
subTowNumbers(number1: 1, number2: 1, method: {
(a:Int, b:Int) -> Int in
return a + b
})
subTowNumbers(number1: 1, number2: 1, method: sum)
//用+代替求和闭包
subTowNumbers(number1: 1, number2: 1, method: + )
subTowNumbers(number1: 2, number2: 3, method: * )
subTowNumbers(number1: 2, number2: 3){ $0 * $1 }
6.Swift语言中的泛型编程
//泛型是另一个可以使编码更加简单、快捷的方式,可以理解为泛指所有类型。
//将一个整型数组合并到另一个整型数组
func appendToIntArray(array:[Int], toArray:inout [Int])
{
for item in array
{
toArray.append(item)
}
}
var array = [1, 2, 3]
appendToIntArray(array: [4, 5, 6], toArray: &array)
func appendToStringArray(array:[String], toArray:inout [String])
{
for item in array
{
toArray.append(item)
}
}
var arrayString = ["Objective-C", "Java"]
appendToStringArray(array: ["Swift", "Python"], toArray: &arrayString)
//在函数名称右侧使用尖括号<>声明一个泛型,大写T表示任意的类型
func appendToGenericArray<T>(array:[T], toArray:inout [T])
{
for item in array
{
toArray.append(item)
}
}
var anotherIntArray = [1, 2, 3]
appendToGenericArray(array: [4, 5, 6], toArray: &anotherIntArray)
var anotherStringArray = ["Objective-C", "Java"]
appendToGenericArray(array: ["Swift", "Python"], toArray: &anotherStringArray)
var anotherCGPointArray = [CGPoint(x:0, y:0), CGPoint(x:10, y:10) ]
appendToGenericArray(array: [CGPoint(x:20, y:20), CGPoint(x:30, y:30)], toArray: &anotherCGPointArray)
7.Swift的do-try-catch错误处理模式
enum ErrorType: Error
{
case invalidProduct
case insufficientCoins(coinsNeeded: Int)
case outOfStock
}
///商品
struct Product
{
var price: Int
var count: Int
}
//当前总金额
var totalCoins = 20
//商店
class Shop
{
var products =
[
"Pudding": Product(price: 12, count: 7),
"Donut": Product(price: 10, count: 4),
"Cheesepuff": Product(price: 7, count: 11)
]
func sell(productName: String) throws
{
//guard-let和if-let类似,都是根据其后的表达式的布尔值,决定下一步做什么。
guard let product = products[productName] else
{
throw ErrorType.invalidProduct
}
//通过throw关键词,抛出异常,即提示错误的具体信息。当需要在函数或者方法里抛出异常,使用throw就可以。
guard product.count > 0 else
{
throw ErrorType.outOfStock
}
guard product.price <= totalCoins else
{
throw ErrorType.insufficientCoins(coinsNeeded: product.price - totalCoins)
}
totalCoins -= product.price
var newItem = product
newItem.count -= 1
products[productName] = newItem
print(">>>>>> \(productName)")
}
}
var shop = Shop()
//do-catch语句就是尝试做一件事情,如果失败则捕获出现的错误。
do
{
// try shop.sell(productName: "Apple")
try shop.sell(productName: "Pudding")
try shop.sell(productName: "Pudding")
}
catch ErrorType.invalidProduct
{
print("Invalid product.")
}
catch ErrorType.outOfStock
{
print("Out of Stock.")
}
catch ErrorType.insufficientCoins(let coinsNeeded)
{
print("Need an additional \(coinsNeeded) coin(s).")
}
8.实例的引用特征和Swift的内存管理
//Swift使用自动引用计数,跟踪并管理应用分配的内存。
class Person
{
var name : String
init(name: String)
{
self.name = name
}
deinit
{
print("-------- deinit")
}
}
var person :Person? = Person(name: "Bill")
var person2 = person
var person3 = person
person = nil
person2 = nil
person3 = nil
9.实例的交叉引用和弱引用(weak)
class People
{
var name : String
var pet : Pet?
init(name:String)
{
self.name = name
print("People is initialized.")
}
deinit
{
print("People is deinitialized.")
}
}
class Pet
{
var name : String
weak var master : People? //weak关键字,进行弱引用
init(name:String)
{
self.name = name
print("Pet is initialized.")
}
deinit
{
print("Pet is deinitialized.")
}
}
var master:People?
var dog:Pet?
master = People(name: "Jerry")
dog = Pet(name: "Dog")
master!.pet = dog
dog!.master = master
master = nil
dog = nil
10.Swift的懒加载(lazy initialization)使用解析
//懒加载:用到时候才会开辟内存空间,多次使用只会加载一次,关键词:lazy
class Demo
{
var url:NSString
lazy var completeURL:NSString =
{
[unowned self] in
if self.url.hasPrefix("http://")
{
return self.url
}
else
{
return "http://\(self.url)" as NSString
}
}()
init(url:NSString)
{
self.url = url
}
}
let demo = Demo(url: "www.coolketang.com")
demo.url
demo
demo.completeURL
demo