今是昨非

今是昨非

日出江花红胜火,春来江水绿如蓝

Swift代碼中的嵌套命名法

Swift 程式碼中的嵌套命名法#

Swift 支持與其他類型嵌套命名,儘管它還沒有專用的命名關鍵字。下面我們來看看,如何使用類型嵌套來優化我們程式碼的結構。

大多數 Swift 開發者習慣於用類型在結構上的實際名字累命名。例如:PostTextFormatterOption(一個 Text Formatter 類型的用於格式化 Posts 的 Option)。這可能是因為我們在 Objective-C & C 中,養成的別無選擇的可怕命名習慣,被我們帶到了 Swift 裡。

下面我們用上面提到的類型作為例子,來看下 Post、PostTextFormatter 以及 PostTextFormatterOption 的實現:

struct Post {
    let id: Int
    let author: User
    let title: String
    let text: String
}

class PostTextFormatter {
    private let options: Set
    
    init(options: Set) {
        self.options = options
    }

    func formatTitle(for post: Post) -> String {
        return post.title.formatted(withOptions: options)
    }

    func formatText(for post: Post) -> String {
        return post.text.formatted(withOptions: options)
    }
}

enum PostTextFormatterOption {
    case highlightNames
    case highlightLinks
}

然後我們再來看一下,如果我們把上面的類型作為 Post 的嵌套類型,會發生什麼?

struct Post {
    class TextFormatter {
        enum Option {
            case highlightNames
            case highlightLinks
        }

        private let options: Set

        init(options: Set) {
            self.options = options
        }

        func formatTitle(for post: Post) -> String {
            return post.title.formatted(withOptions: options)
        }

        func formatText(for post: Post) -> String {
            return post.text.formatted(withOptions: options)
        }
    }

    let id: Int
    let author: User
    let title: String
    let text: String
}

上面嵌套類型的一個很大的優點是,我們掃一眼就可以很明白的看到類型之間的結構和關係。而且我們還減少了初始化程式碼的冗長,使它更短更易閱讀(options 參數類型從 Set<PostTextFormatterOption> 變為 Set< Option >)。

調用層級也更加簡潔明瞭 —— 所有和 Post 有關的整潔的變為 Post.namespace。一個 post 的文本的格式化看起來如下:

let formatter = Post.TextFormatter(options: [.highlightLinks])
let text = formatter.formatText(for: post)

然而,使用嵌套類型還有一個不容忽視的壞處。程式碼看起來 “反了”,因為父類型的實際內容被擠到了最下面。我們試著來修復一下這個問題,把嵌套類型的程式碼從上面移到下面(為了好分辨,還添加一些 MARKs)

struct Post {
    let id: Int
    let author: User
    let title: String
    let text: String

    // MARK: - TextFormatter
    class TextFormatter {
        private let options: Set

        init(options: Set) {
            self.options = options
        }

        func formatTitle(for post: Post) -> String {
            return post.title.formatted(withOptions: options)
        }

        func formatText(for post: Post) -> String {
            return post.text.formatted(withOptions: options)
        }

        // MARK: - Option
        enum Option {
            case highlightNames
            case highlightLinks
        }
    }
}

嵌套類型放上面還是下面純粹是個人偏好。我比較喜歡把父類型的內容放在上面 —— 同時還可以享受嵌套類型的便利。

事實上,在 Swift 中還有好幾種其他方法可以實現命名、嵌套類型。

使用 extension 實現嵌套類型#

另一個實現嵌套類型的選擇就是 extension。這種方法可以在實現和調用時保持層級關係,同時清楚明白的分開每種類型。

看起來如下:

struct Post {
    let id: Int
    let author: User
    let title: String
    let text: String
}

extension Post {
    class TextFormatter {
        private let options: Set

        init(options: Set) {
            self.options = options
        }

        func formatTitle(for post: Post) -> String {
            return post.title.formatted(withOptions: options)
        }

        func formatText(for post: Post) -> String {
            return post.text.formatted(withOptions: options)
        }
    }
}

extension Post.TextFormatter {
    enum Option {
        case highlightNames
        case highlightLinks
    }
}

使用 typealiases#

也可以使用 typealiases。在原始程式碼裡添加 typealiases 來實現類似嵌套類型的程式碼(實際上並沒用嵌套類型)。儘管這種方法在實現上並沒有嵌套層級關係,但是卻減少了冗長程式碼 —— 並且調用看起來也和使用嵌套類型一樣。

程式碼如下:

struct Post {
    typealias TextFormatter = PostTextFormatter

    let id: Int
    let author: User
    let title: String
    let text: String
}

class PostTextFormatter {
    typealias Option = PostTextFormatterOption

    private let options: Set

    init(options: Set) {
        self.options = options
    }

    func formatTitle(for post: Post) -> String {
        return post.title.formatted(withOptions: options)
    }

    func formatText(for post: Post) -> String {
        return post.text.formatted(withOptions: options)
    }
}

enum PostTextFormatterOption {
    case highlightNames
    case highlightLinks
}

最後#

使用嵌套類型有助於寫出優雅結構、層級的程式碼,使多種類型之間的關係更加清楚明瞭 —— 不管是在實現上,還是調用上。

然而,由於實現方法的不同,可能會遇到不同的挑戰和副作用 —— 所以我認為根據實際情況選擇對應的實現很重要,為了贏得漂亮。

你認為呢?上面那些技術,你傾向於用哪種?或者你還有其他的方法?告訴我你的問題、看法,Twitter@johnsundell

感謝閱讀!🚀

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。