Swift tricks系列收集Swift牛逼的patterns和讓你代碼更加Swifty的tricks,持續更新中……
Phantom Types
在項目中,某些業務是需要按照嚴格的流程和規范進行的,舉個??
func getSecretData() -> String {
return "secretedata";
}
func encrypt(secretData : String) -> String {
return "encryptdata";
}
func sendEncryptData(encryptdata : String){
// send encrypt data
}
//首先獲取秘密信息
var secretedata = getSecretData()
//對秘密信息加密
var encryptdata = encrypt(secretedata)
//發送加密信息
sendEncryptData(encryptdata)
上面的例子必須嚴格按照“獲取信息”->“加密”->“發送”的流程來,否則就會產生安全問題!
但是程序員是人,是人就會犯錯誤。如果一個粗心的程序員寫了下面的代碼,那將會產生災難性的后果:
var secretedata = getSecretData()
sendEncryptData(secretedata)
腫么辦?能不能通過代碼來保證流程呢?Yes, we can!
一般的做法是醬紫的:
struct SecretData {
let secretedata:String
}
struct EncryptData {
let encryptdata:String
}
func getSecretData() -> SecretData {
return SecretData(secretedata:"secretedata");
}
func encrypt(secretData : SecretData) -> EncryptData {
return EncryptData(encryptdata:"encryptdata");
}
func sendEncryptData(encryptdata : EncryptData){
// send encrypt data
}
var secretedata = getSecretData()
var encryptdata = encrypt(secretedata)
sendEncryptData(encryptdata)
這樣我們就能避免粗心程序員造成的錯誤 。因為當你試圖執行sendEncryptData(secretedata)
的時候,編譯器會報錯!
在上面的方法中,我們定義了兩個struct
,這兩個struct
除了名字不一樣外,其他都是一模一樣。設想一下,如果struct
里面的字段稍微多一點,我們的代碼將是這樣的:
struct SecretData {
let secretedata:String
let encyptMehod:String
let encyptKey:String
let from:String
let to:String
......
}
struct EncryptData {
let encryptdata:String
let encyptMehod:String
let encyptKey:String
let from:String
let to:String
......
}
這……就有點不怎么Swifty了。
腫么辦?
Phantom Types!
enum Encrypted {}
enum Decrypted {}
struct SecretData<T> {
let secretedata:String
let encyptMehod:String
let encyptKey:String
let from:String
let to:String
}
func getSecretData() -> SecretData<Decrypted> {
return SecretData(secretedata:"secretedata", encyptMehod:"nb", encyptKey:"xxx",from:"agent",to:"gcd");
}
func encrypt(secretData : SecretData<Decrypted>) -> SecretData<Encrypted> {
return SecretData(secretedata:"secretedata", encyptMehod:"nb", encyptKey:"xxx",from:"agent",to:"gcd");
}
func sendEncryptData(encryptdata : SecretData<Encrypted>)
{
// send encrypt data
}
var secretedata = getSecretData()
var encryptdata = encrypt(secretedata)
sendEncryptData(encryptdata)
Encrypted
和Decrypted
是兩個Phantom Type,我們通過一個范型struct
解決了重復定義屬性的問題。
PS:看到沒有case的
enum
不要驚訝,這是Phantom Type的精髓