鍍金池/ 教程/ iOS/ 造個類型不是夢-白話 Swift 類型創(chuàng)建
特性(Attributes)
Access Control 權(quán)限控制的黑與白
基本運算符(Basic Operators)
基礎(chǔ)部分(The Basics)
閉包(Closures)
擴(kuò)展
泛型參數(shù)(Generic Parameters and Arguments)
訪問控制和 protected
語句(Statements)
模式(Patterns)
WWDC 里面的那個“大炮打氣球”
關(guān)于語言參考(About the Language Reference)
語法總結(jié)(Summary of the Grammar)
嵌套類型
類型(Types)
Swift 初見(A Swift Tour)
泛型
枚舉(Enumerations)
高級運算符
繼承
析構(gòu)過程
關(guān)于 Swift(About Swift)
訪問控制
類和結(jié)構(gòu)體
內(nèi)存安全
Swift 與 C 語言指針友好合作
協(xié)議
屬性(Properties)
可選類型完美解決占位問題
錯誤處理
字符串和字符(Strings and Characters)
聲明(Declarations)
自動引用計數(shù)
Swift 里的值類型與引用類型
表達(dá)式(Expressions)
Swift 文檔修訂歷史
造個類型不是夢-白話 Swift 類型創(chuàng)建
歡迎使用 Swift
詞法結(jié)構(gòu)(Lexical Structure)
集合類型(Collection Types)
下標(biāo)
方法(Methods)
可選鏈?zhǔn)秸{(diào)用
版本兼容性
類型轉(zhuǎn)換
構(gòu)造過程
The Swift Programming Language 中文版
函數(shù)(Functions)
Swift 教程
控制流(Control Flow)

造個類型不是夢-白話 Swift 類型創(chuàng)建


翻譯:老碼團(tuán)隊翻譯組-Tyrion 校對:老碼團(tuán)隊翻譯組-Oberyn

本頁包含內(nèi)容:

小伙伴們,Swift 中的 Bool 類型有著非常重要的語法功能,并支撐起了整個 Swift 體系中的邏輯判斷體系,經(jīng)過老碼的研究和學(xué)習(xí), Bool 類型本身其實是對基礎(chǔ) Boolean 類型封裝,小伙伴們可能咬著手指頭問老碼,怎么一會 Bool 類型,一會 Boolean 類型,其區(qū)別在于,前者是基于枚舉的組合類型,而后者則是基本類型,只有兩種 true 和 false。

自定義原型

接下老碼根據(jù) Bool 的思想來創(chuàng)建一個 OCBool 類型,來讓小伙伴們了解一下 Swift 中到底是怎么玩兒的。 來我們先看一下 OCBool 的定義。

代碼示例如下:
enum OCBool{
case ocTrue
case ocFalse
}
注意:
  • 代碼中第2行和第3行,可以合并到一行寫,如蘋果官方 Blog 所寫的一樣
  • 代碼中命名需要注意:OCBool 是類型名,所以首字母必須大寫,而 case 中的 ocTrue 和 ocFalse 是小類型則需要首字母小寫。

實現(xiàn)默認(rèn)值

行,我們給了一個漂亮的定義,不過按照傳統(tǒng)語言的經(jīng)驗,Bool 值默認(rèn)情況下是假, 所以我們的 OCBool 也應(yīng)該如此,我們使用類型擴(kuò)展技術(shù)增加這個默認(rèn)特性:

extension OCBool{
     init(){
             self =.ocFalse
     }
}
注意:
  • 代碼中第1行:extension 關(guān)鍵字,非常強(qiáng)大,小伙伴們可以通過此創(chuàng)造出許多好玩的東西,建議各位去 Github 上看一個名為“Swiftz”的項目,它將擴(kuò)展用到了極致。
  • 代碼中第3行:self = .ocFalse 語法,剛?cè)腴T的小伙伴們很迷糊,為什么會有奇怪的點語法,因為大牛 Chris 在 Swift 中增加了類型智能推斷功能,在蘋果 Blog 中,提到了“Context”概念,就是這個意思,因為這行語句是在枚舉 OCBool 中的,其上下文就是 OCBool 的定義體,編譯器當(dāng)然知道.ocFalse 就是 OCBool.ocFalse 了,所以這里直接點語法,非常整齊。 現(xiàn)在我們可以使用如下方法使用這個 Bool 類型。
代碼示例如下:
var result:OCBool = OCBool()
var result1:OCBool = .ocTrue

支持基本布爾型初始化

正如上述代碼所述,我們只能通過類型或者枚舉項目賦值,這是組合類型的用法,但是編碼的日子里,我們總是希望和 true,false 直接打交道,也就是說,我們希望這么做, 代碼示例如下:

var isSuccess:OCBool = true

如果小伙伴們直接這么用,則會出現(xiàn)如下錯誤:

/Users/tyrion-OldCoder/Documents/Learning/BoolType/BoolType/main.swift:30:24: Type 'OCBool' does not conform to protocol 'BooleanLiteralConvertible'

編譯器咆哮的原因是,我們的類型沒有遵從“布爾字面量轉(zhuǎn)換協(xié)議”,接下來修正這個問題,

代碼示例如下:
import Foundation

println("Hello, World!")

enum OCBool{
    case ocTrue
    case ocFalse
}

extension OCBool: BooleanLiteralConvertible{
static func convertFromBooleanLiteral( value: Bool) ->OCBool{
    return value ? ocTrue : ocFalse
    }
}

var isSuccess:OCBool = true
注意:
  • 代碼中的第11行是重點,我的類型 OCBool 支持了 BooleanLiteralConvertible 協(xié)議,這個協(xié)到底是干什么的呢,小伙伴們在 Xcode 代碼編輯器,按住 Command 鍵,然后點擊第11行中的 BooleanLiteralConvertible 協(xié)議名,則會進(jìn)入它的定義,
    其定義如下:
protocol BooleanLiteralConvertible {
    typealias BooleanLiteralType
    class func convertFromBooleanLiteral(value: BooleanLiteralType) -> Self
}
  • 這個定義中有個類方法 convertFromBooleanLiteral,它的參數(shù)為 BooleanLiteralType 類型,也就是我傳入的 Bool 類型, 且返回值為實現(xiàn)這個協(xié)議的類型本身,在我們的 OCBool 類型中,其返回值就是 OCBool 本身。經(jīng)過這個定義,我們可以直接對 OCBool 類型直接進(jìn)行布爾字面量初始化了。

支持 Bool 類型判斷

小伙伴們不安分, 肯定想著我怎么用它實現(xiàn)邏輯判斷,所以如果你這么寫,

代碼示例如下:
var isSuccess:OCBool = true

if isSuccess {
    println("老碼請你吃火鍋!")
}

你永遠(yuǎn)吃不到老碼的火鍋,因為這里編譯器會咆哮:

/Users/tyrion-OldCoder/Documents/Learning/BoolType/BoolType/main.swift:27:4: Type 'OCBool' does not conform to protocol 'LogicValue'

OCBool 現(xiàn)在只能用 bool 類型初始化,而不能直接返回 bool 型,小火把們還記得在《老碼說編程之白話 Swift 江湖》中,老碼多次提到,媽媽再也不擔(dān)心我們 if a = 1{}的寫法了, 因為等號不支持值返回了, 所以在 if 判斷是后面的條件必須有返回值,OCBool 沒有,所以編譯器哭了。我們解決這個問題。

代碼示例如下:
import Foundation

println("Hello, World!")

enum OCBool{
    case ocTrue
    case ocFalse
}

extension OCBool: BooleanLiteralConvertible{
static func convertFromBooleanLiteral( value: Bool) ->OCBool{
    return value ? ocTrue : ocFalse
    }
}

extension OCBool: LogicValue{
    func getLogicValue() ->Bool {
        var boolValue: Bool{
        switch self{
        case .ocTrue:
            return true
        case .ocFalse:
            return false
            }
        }
        return boolValue
    }
}

var isSuccess:OCBool = true

if isSuccess {
    println("老碼請你吃火鍋!")
}

運行結(jié)果如下:

Hello, World!
老碼請你吃火鍋!
Program ended with exit code: 0
注意:
  • 如果小伙伴們現(xiàn)在用的是 Beta 版的 Xcode,注意蘋果官方 Blog 中,在代碼第17行如果在 Xcode Beta4下是錯誤的,這里的協(xié)議是,LogicValue 而不是 BooleanVue,所以記得看錯誤提示才是好習(xí)慣。
  • 注意代碼第34行,完美支持 if 判斷,且輸出結(jié)果為“老碼請你吃火鍋”,老碼也是說說而已,請不要當(dāng)真。

支持兼容各們各派的類型

小伙伴們,江湖風(fēng)險,門派眾多,老碼有自己的 OCBool 類型,可能嵩山少林有自己的 SSBool 類型,甚至連郭美美都可能有自己的 MMBool 類型,所以 OCBool 必須能夠識別這些類型,這些各門各派的類型,只要支持 LogicValue 協(xié)議,就應(yīng)該可以被識別,看老碼怎么做,

代碼示例如下:
extension OCBool{
    init( _ v: LogicValue )
    {
        if v.getLogicValue(){
            self = .ocTrue
        }
        else{
            self = .ocFalse
        }
    }

}

var mmResult: Bool = true
var ocResult:OCBool = OCBool(mmResult)

if ocResult {
    println("老碼沒錢,郭美美請你吃火鍋!")
}
代碼運行結(jié)果如下:
Hello, World!
老碼沒錢,郭美美請你吃火鍋!
Program ended with exit code: 0

漂亮!我們的 OCBool 類型現(xiàn)在支持了所有的邏輯變量初始化。

注意:
  • 代碼中第2行:“_”下橫杠的用法,這是一個功能強(qiáng)大的小強(qiáng),在此的目的是屏蔽外部參數(shù)名,所以小伙伴們可以直接:var ocResult:OCBool = OCBool(mmResult)而不是:var ocResult:OCBool = OCBool(v: mmResult),小伙伴們驚呆了!這個 init 函數(shù)中本來就沒有外部參數(shù)名啊,還記得老碼在書里說過沒,Swift 的初始化函數(shù)會默認(rèn)使用內(nèi)部參數(shù)名,作為外部參數(shù)名。

完善 OCBool 的布爾基因體系:

小伙伴們,bool 類型的價值就是在于各種判斷,諸如==,!=, &,|,^,!,以及各種組合邏輯運算,我們 OCBool 也要具備這些功能,否則就會基因缺陷,且看老碼如何實現(xiàn):

extension OCBool: Equatable{
}

//支持等值判斷運算符
func ==( left: OCBool, right: OCBool )->Bool{
    switch (left, right){
    case (.ocTrue, .ocTrue):
            return true
    default:
        return false
    }
}
//支持位與運算符
func &( left:OCBool, right: OCBool)->OCBool{

    if left{
        return right
    }
    else{
        return false
    }
}
//支持位或運算符
func |( left:OCBool, right: OCBool)->OCBool{

    if left{
        return true
    }
    else{
        return right
    }
}

//支持位異或運算符
func ^( left:OCBool, right: OCBool)->OCBool{
    return OCBool( left != right )
}
//支持求反運算符
@prefix func !( a:OCBool )-> OCBool{
    return a ^ true
}
//支持組合求與運算符
func &= (inout left:OCBool, right:OCBool ){
    left = left & right
}

var isHasMoney:OCBool = true
var isHasWife:OCBool = true
var isHasHealty:OCBool = true
var isHasLover:OCBool = true

isHasMoney != isHasHealty
isHasHealty == isHasMoney
isHasWife ^ isHasLover
isHasWife = !isHasLover

if (isHasMoney | isHasHealty) & isHasHealty{
    println("人生贏家,就像老碼一樣!")
}else
{
    println("人生最苦的事事,人死了錢沒花了,人生最苦的事是,人活著,錢沒了!")
}

好了,到這里就到這里了,窗外的雷聲叫醒了老碼,現(xiàn)在應(yīng)該去吃飯了,以上老碼給大家展示了如果制造一個自己的類型,記得老碼的示例是在 Xcode6 Beta4下測試的,至于 Beta5的改變還沒有涉及,小伙伴們要好生練習(xí),以后各種自定類型都是基于這個思想。還有這個章節(jié)不是老碼的原創(chuàng),老碼認(rèn)真的閱讀了蘋果的官方博客,且自己的練習(xí)總結(jié),如果小伙伴們費了吃奶的勁還是看不懂,請找度娘谷歌,還是看不懂請到老碼官方微博:http://weibo.com/u/5241713117咆哮。

本文由翻譯自 Apple Swift Blog :https://developer.apple.com/swift/blog/?id=8