協(xié)議
協(xié)議是方法的集合(計算屬性相當(dāng)于方法)
可以把看似不相關(guān)的對象的公共行為放到一個協(xié)議里
協(xié)議的三種作用
1.能力-遵循了協(xié)議就意味著具備了某種能力
2.約定-遵循了協(xié)議就一定要能實現(xiàn)協(xié)議中的方法
3.角色-一個類可以遵循多個協(xié)議,一個協(xié)議也可以被多個類遵循概疆,遵循協(xié)議就意味著扮演某種角色逗威,遵循多個協(xié)議就以為著可以扮演多種角色
說明:Swift中的繼承是單一繼承(一個類只能有一個父類),如果希望一個類具備多種能力可以使用多個協(xié)議來實現(xiàn)岔冀。(c++里面是通過多重繼承來實現(xiàn)的凯旭,并不好)
依賴倒轉(zhuǎn)原則(面向協(xié)議編程)
1.聲明變量的類型時應(yīng)盡可能使用協(xié)議類型
2.聲明方法參數(shù)類型時應(yīng)盡可能使用協(xié)議類型
3.聲明方法返回類型時應(yīng)盡可能使用協(xié)議類型
開閉原則
1.抽象關(guān)鍵:在設(shè)計系統(tǒng)的時候一定要設(shè)計好模式
2.封裝可變性:橋梁模式-將不同可變因素封裝到不同的繼承結(jié)構(gòu)中
接口隔離,協(xié)議隔離原則
協(xié)議的設(shè)計要小而專不要大而全
協(xié)議的設(shè)計也要高度內(nèi)聚
復(fù)合開閉原則
協(xié)議中全是抽象概念(只有聲明沒有實現(xiàn))遵循協(xié)議的類可以各自對協(xié)議中的計算屬性和方法給出自己的實現(xiàn)版本,這樣當(dāng)我們面向協(xié)議編程時就可以把多態(tài)的優(yōu)勢發(fā)揮到淋漓盡致罐呼,可以寫出更通用更靈活的代碼
例子:打折協(xié)議
/**
* 打折策略協(xié)議
*/
protocol DiscountStrategy {
/**
- parameter price:原價
- returns:折扣的金額
*/
func discount(price:Double) ->Double
}
///百分比折扣策略
class PercentageDiscount:DiscountStrategy {
var percentage:Double
init(percentage:Double){
self.percentage = percentage
}
func discount(price:Double)->Double{
return price*(1-percentage)
}
}
class FixedDiscount:DiscountStrategy {
var fixedMoney:Double
init(fixedMoney:Double){
self.fixedMoney = fixedMoney
}
func discount(price: Double) -> Double {
return price >= fixedMoney ? fixedMoney:0
}
}
class SegmentedDiscount:DiscountStrategy {
func discount(price: Double) -> Double {
if price < 20{
return 0
}else if price<50{
return 3
}else if price < 100 {
return 10
}else{
return 30
}
}
}
//圖書
class Book {
var name:String
var price:Double
var type:String
//四人幫設(shè)計模式-策略模式
var strategy:DiscountStrategy?
/**
初始化方法
- parameter name: 書名
- parameter price:間隔
- parameter type:類型
*/
init(name:String,price:Double,type:String){
self.name = name
self.price = price
self.type = type
}
/// 減了多少錢
var discountValue:Double{
get{
if let s = strategy{
return s.discount(price)
}else{
return 0
}
}
}
///折扣后的價格
var discountedPrice:Double{
get{return price - discountValue}
let booksArray = [
Book(name: "C語言程序設(shè)計", price: 24.0, type: "計算機(jī)"),
Book(name: "名偵探柯南", price: 98.5, type: "漫畫"),
Book(name: "Swift從入門到精通", price: 35.8, type: "計算機(jī)"),
Book(name: "黃岡教學(xué)密集卷", price: 34.2, type: "教材"),
Book(name: "中國股市探秘", price: 58.5, type: "金融")]
let discountDict:[String:DiscountStrategy] = [
"計算機(jī)" : PercentageDiscount(percentage:0.78),
"教材" : PercentageDiscount(percentage:0.85),
"漫畫" : SegmentedDiscount(),
"科普" : FixedDiscount(fixedMoney:2)
]
var totalprice = 0.0
var totalDiscount = 0.0
for book in booksArray {
if let strategy = discountDict[book.type]{
book.strategy = strategy
}
print("《\(book.name)》原價:¥\(book.price)元")
print("《\(book.name)》折扣后:¥\(book.discountedPrice)")
totalprice += book.discountedPrice
totalDiscount += book.discountValue
}
print(String(format:"總計:¥%.1f元",totalprice))
print(String(format:"總計:¥%.1f元",totalDiscount))
計算機(jī)的硬件構(gòu)成
運(yùn)算器鞠柄,控制器,存儲器嫉柴,輸入設(shè)備厌杜,輸出設(shè)備
運(yùn)算器+存儲器=cpu(中央處理器)
存儲器=內(nèi)存(Ram - random access memory)
程序員可以使用的內(nèi)存
1.堆(Stack)- 我們創(chuàng)建的對象都是放在堆上的
2.棧(heap)- 我們定義的局部變量臨時都是放在棧上的
3.靜態(tài)區(qū)域(static area)
- 數(shù)據(jù)段--全局量
- 只讀數(shù)據(jù)段--常量
- 代碼段--函數(shù)和方法
值類型和引用類型的區(qū)別
1.結(jié)構(gòu)的對象是值類型,類型的對象是引用類型
值類型在賦值的時候會在內(nèi)存中進(jìn)行對象拷貝
引用類型在賦值時的時候不會進(jìn)行對象拷貝只是能加一個引用
2.結(jié)構(gòu)中會自動生成初始化方法
3.結(jié)構(gòu)中方法默認(rèn)情況下是不允許改變結(jié)構(gòu)中的屬性的计螺,除非加上Mutating關(guān)鍵字
自動內(nèi)存處理機(jī)制
class Person {
var name :String
var age:Int
// 指派構(gòu)造器(designated)
init(name:String,age:Int){
print("創(chuàng)建人")
self.name = name
self.age = age
}
//將構(gòu)造器轉(zhuǎn)化為必要構(gòu)造器
//子類里必須遵循父類構(gòu)造
// required init(name:String,age:Int){
// print("創(chuàng)建人")
// self.name = name
// self.age = age
// }
//默認(rèn)賦值,便利構(gòu)造器(convenience)
//只能橫向調(diào)用夯尽,不能跨類
convenience init(){
//下面的語句必須寫在調(diào)用自己的初始化方法之后否則MAJOR屬性會被附上不正確的值
self.init(name:"無名",age:20)
}
deinit{
print("銷毀人")
}
}
class Student:Person {
var major:String
// //重寫
// override init(){
// self.major = major
// print("創(chuàng)建學(xué)生")
// }
init(name:String,age:Int,major:String){
//子類只能調(diào)用直接父類的構(gòu)造器
//只能調(diào)用非便利構(gòu)造器(指派構(gòu)造器)
self.major = major//1初始化自己特有的屬性
super.init(name: name, age: age)//2初始化二階段
//此處可以調(diào)用對象方法,已完成初始化
}
func study(){
}
//釋放時不需要傳參
deinit{
print("銷毀學(xué)生")
}
}
class Teacher: Person {
// override init(){
// print("創(chuàng)建老師")
// }
override init(name:String,age:Int){
super.init(name: name, age: age)
}
deinit{
print("銷毀老師")
}
}
////創(chuàng)建一個學(xué)生對象危尿,然后用stu去引用它呐萌,所以此時學(xué)生對象引用計數(shù)為1
////只要有一個對象引用,就不會刪除,銷毀(及時性銷毀優(yōu)于andrid)
//var stu:Student? = Student()
////取消全部引用就會銷毀
////stu=nil
////此處沒有創(chuàng)建新的學(xué)生對象谊娇,原來的學(xué)生對象的引用計數(shù)+1
//var stu2 = stu
////同上肺孤,原來的學(xué)生對象的引用計數(shù)+1
//var stu3 = stu2
////學(xué)生對象引用計數(shù)-1
//stu=nil
////學(xué)生對象引用計數(shù)-1
//stu2=nil
////學(xué)生對象引用計數(shù)-1
//stu3=nil
////當(dāng)學(xué)生對象引用計數(shù)為0時ARC會自動清理內(nèi)存釋放學(xué)生對象
////ARC及時性的內(nèi)存清理 優(yōu)于JAVA中Garbage collection(垃圾回收)
//var stu1:Student? = Student()
////弱引用,雖然引用济欢,但不會增加引用計數(shù) 默認(rèn)是強(qiáng)引用(會增加引用計數(shù))
//weak var stu2 = stu1
//
//weak var stu3 = stu2
//
//stu1=nil
////如果想釋放內(nèi)存赠堵,釋放內(nèi)存最好方式是手動將一個引用賦值為nil
//而這里是全局變量,函數(shù)調(diào)用不會使其消失
//var stu:Student?
//
//func foo(){
//// //局部變量,函數(shù)調(diào)用結(jié)束后局部變量就消失了
// //所以學(xué)生對象的引用計數(shù)也就變成0了法褥,所以會被ARC釋放掉
//// let stu = Student()
// print(stu)
//}
//
//foo()
//棧 -FILO 先進(jìn)后出結(jié)構(gòu)
//創(chuàng)建任何子類對象的時候一定是先創(chuàng)建父類對象
//var stu:Person = Student()
////如果一個引用轉(zhuǎn)移了(會導(dǎo)致原來對象的引用計數(shù)-1 新對象引用計數(shù)+1)
////棧存儲茫叭,先進(jìn)后出
//stu = Teacher()
//stu = Person()
//超出自動釋放池不會起作用
//var stu:Student?
//swift自動釋放池
//通過向AUTOreleasepool函數(shù)中傳入一個閉包來實現(xiàn)
//autoreleasepool { () -> () in
// //自動釋放池中的對象引用在池的邊界引用計數(shù)會自動-1的消息
// //將來做IOS開發(fā)時,如果某個地方會創(chuàng)建很多的臨時對象
// //那么最好在此處設(shè)置一個自動釋放池避免內(nèi)存順時峰值過高
// let stu = Student()
// let stu2 = stu
//}
//// 離開自動釋放池時,Stu會受到引用計數(shù)減1消息半等,Stu2也會受到引用計數(shù)減1得消息
//OC用法
//@autoreleasepool
//雙向關(guān)聯(lián)關(guān)系
//如果程序中出現(xiàn)了類與類之間雙向關(guān)聯(lián)揍愁,必須要將其中一端設(shè)置成weak引用,否
//則將會形成循環(huán)引用杀饵,導(dǎo)致ARC無法釋放內(nèi)存
class Emp {
//推薦使用
//如果允許可控類型通常用WEAK來破除循環(huán)引用
//如果員工關(guān)聯(lián)的部門對象被釋放了那么dept會被賦值為NIL
//如果要繼續(xù)給dept發(fā)消息不會崩潰
//weak var dept:Dept?
//謹(jǐn)慎使用
//如果不允許使用可空類型就必須使用UNOWNED來破除循環(huán)引用
//需要注意的是如果員工對象關(guān)聯(lián)的部門對象被釋放了
//如果還要通過員工對象操作它所關(guān)聯(lián)的部門對象將導(dǎo)致程序崩潰
//錯誤提示EXE_BAD_ACCESS
var dept:Dept?
init() {
print("創(chuàng)建一個員工")
}
deinit{
print("銷毀員工")
}
}
class Dept {
weak var manager : Emp?
init(){
print("創(chuàng)建一個部門")
}
deinit{
print("銷毀部門")
}
}
//func bar() {
// _ = Person()
// let emp = Emp()
// let dept = Dept()
// //引用計數(shù)無限莽囤,破除環(huán)可解除環(huán),方法WEAK
// emp.dept = dept
// dept.manager = emp
//}
//
//bar()
////視圖閉包
//var x :(Int,Int)->Bool = {
// [weak self](x,y) -> Bool in
// return true
//}
泛型
//通用版 類型為虛擬類型(泛型)
func mySwap<T>(inout a:T,inout _ b:T){
let temp = a
a=b
b=temp
}
//swift自動推斷類型
var a="字符",b="墜馬"
mySwap(&a, &b)
print(a,b)