度量單位

作者:KHANLOU,原文鏈接,原文日期:2016-03-18
譯者:Prayer;校對:shanks;定稿:千葉知風(fēng)

在我正在做的一個項(xiàng)目中,有大量關(guān)于度量單位的處理。(或許我應(yīng)該繼續(xù)去推進(jìn)項(xiàng)目進(jìn)展而不是在這兒寫這篇博客)

我總是覺得對度量單位的建模是一件很有意思的事情。比如說,時間單位,假設(shè)你有一個 API 接受一個時間作為參數(shù),可能需要以秒作為單位(又或者是毫秒作為單位)但是,有的時候你有需要以小時為單位來表達(dá)時間,例如 2 小時。所以,為了避免魔數(shù)(magic number) (7200 兩小時轉(zhuǎn)換為秒為單位),你會使用 2 * 60 * 60 ,為了增加可讀性還會在其中的操作符之間加上空格。

然而,7200 這個數(shù)字并沒有什么實(shí)際意義。如果你對著這個數(shù)字看很長時間,擁有很好的數(shù)學(xué)計算功底的話,有可能你會猜到這個數(shù)字代表著兩個小時包含的秒數(shù)。然而如果不是整數(shù)個小時換算成秒的話,你可能永遠(yuǎn)也猜不出來。

在你的應(yīng)用中,7200 這個魔數(shù)不斷的傳遞和使用,這個數(shù)字的度量單位是什么將變得越來越不清晰。

我們需要使用一種方式,將整數(shù)和元數(shù)據(jù)的信息關(guān)聯(lián)起來。將類型描述為度量單位 這篇文章有過相關(guān)的討論,但是我們能否解決不同單位的度量問題,并且使用類型來描述呢?如果這樣的話,當(dāng)我們用 2 小時加上 30 分鐘的時候,就不會得到 32 這樣無意義的結(jié)果。

(當(dāng)然,也有一些語言層面解決這個問題的方案,但是大多數(shù)的語言不支持這樣的操作)

我們?nèi)匀幌M軌蛴?2 個小時加上 30 分鐘,并且得到一個有意義的結(jié)果,所以在我們的類型系統(tǒng)中,Time 需要是一個度量實(shí)體,同時 HoursSeconds 也需要是。

表示 Time 的可以有多個單位,這些單位都必須能夠以秒的方式來度量。

swif
protocol Time {
    var inSeconds: Double { get }
}

每個時間的單位類型都是獨(dú)立的,但是都需要遵守 Time 協(xié)議。

struct Hours: Time {
    let value: Double
    
    var inSeconds: Double {
        return value * 3600
    }
}

struct Minutes: Time {
    let value: Double
    
    var inSeconds: Double {
        return value * 60
    }
}

我們可以使用同樣的方式來定義 Seconds,DaysWeeks 等等結(jié)構(gòu)體,需要注意的是,如果時間單位過大,將會損失一些精度。

現(xiàn)在我們理解了度量單位的刻畫方式,我們可以來進(jìn)行一些度量單位的計算了。

func + (lhs: Time, rhs: Time) -> Time {
    return Seconds(value: lhs.inSeconds + rhs.inSeconds)
}

我們還可以加上一些好用的擴(kuò)展:

extension Time {
    var inMinutes: Double {
        return inSeconds / 60
    }
    
    var inHours: Double {
        return inMinutes / 60
    }
}

為系統(tǒng)的 Int 類型加上類似 DSL 的擴(kuò)展,代碼思路是從 ActiveSupport 中借鑒的:

extension Int {
    var hours: Time {
        return Hours(value: Double(self))
    }
    
    var minutes: Time {
        return Minutes(value: Double(self))
    }
}

利用我們的類型系統(tǒng),我們可以寫出短小但是表意明確的代碼:

let total = 2.hours + 30.minutes

(當(dāng)然結(jié)果是以 Seconds 為單位表示的,可能我們希望引入一個表示層來將這個結(jié)果以更加有意義的方式展現(xiàn)給用戶。我在做的那個項(xiàng)目中有這方面的工作,不過是用 JavaScript 寫的,不支持這樣的類型系統(tǒng),就少了很多樂趣)

本文由 SwiftGG 翻譯組翻譯,已經(jīng)獲得作者翻譯授權(quán),最新文章請訪問 http://swift.gg。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容