Swift 中的数据封装

Posted

技术标签:

【中文标题】Swift 中的数据封装【英文标题】:Data encapsulation in Swift 【发布时间】:2014-07-28 23:42:22 【问题描述】:

我已经阅读了整个Swift book,并观看了所有WWDC videos(我衷心推荐所有这些)。我担心的一件事是数据封装。

考虑以下(完全人为的)示例:

class Stack<T>

    var items : T[] = []

    func push( newItem: T ) 
        items.insert( newItem, atIndex: 0 )
    

    func pop() -> T? 
        if items.count == 0 
            return nil;
        

        return items.removeAtIndex( 0 );
    

这个类实现了一个堆栈,并使用一个数组来实现它。问题是,items(就像 Swift 中的所有属性一样)是公共的,所以没有什么可以阻止任何人直接访问(甚至变异)它,而不是公共 API。作为一个脾气暴躁的老 C++ 人,这让我很不爽。

我看到人们抱怨缺少访问修饰符,虽然我同意他们会直接解决这个问题(我听说他们可能很快就会实施(TM)),但我想知道数据隐藏的一些策略是什么他们的缺席。

我是否遗漏了什么,或者这只是语言中的一个遗漏?

【问题讨论】:

可能重复:***.com/q/24003918/1639670 实际上有一种方法可以进行某种数据隐藏——协议。只需使您的类符合您的协议,并包含您希望对外界可见的所有功能和内容,并传递它而不是类本身。正如我所说,这不是替代品,但会一直工作到可见性修饰符结束。这也是一个很好的设计模式——依赖注入 " 所以没有什么能阻止任何人直接访问(甚至变异)它与公共 API 分开” - 除了成为一个“脾气暴躁的老 C++ 家伙” :-) 你认为会发生什么伤害如果您不强制阻止人们以他们想要的方式使用您的代码?例如,Python 有一句谚语“我们在这里都是成年人”。公共/私有基于文档和约定。如果有人想摆弄课堂内部的东西,请注意购买者。没有人会假装他们可以永远知道没有人有充分的理由访问内部对象。 【参考方案1】:

它现在只是丢失了。 Greg Parker 已明确表示 (in this dev forums thread) 即将推出可见性修饰符。

鉴于没有标题,标准的 Objective-C 技巧将不起作用,我想不出另一个不涉及大量向后弯曲的限制可见性的技巧。由于已经承诺了语言功能,我不确定它是否值得任何大笔投资。

从好的方面来说,由于此功能不断变化,现在是file a radar 并影响结果的好时机。

【讨论】:

【参考方案2】:

事实上,我很高兴 Swift 终于采用了静态类型,因此符合具有最佳 OO 属性的代码的理论,但标题的下降仍然打破了面向对象编程的非常小的含义,即封装。 Eiffel 的一种出路是自动提取标头,但不指定哪些是公共接口,哪些是私有接口,这将毫无价值。我对苹果的这一举动感到非常痛心。

【讨论】:

【参考方案3】:

更新答案以供将来参考。

来自苹果的documentation:

访问级别

Swift 提供了三种不同的访问级别 代码中的实体。这些访问级别是相对于 定义实体的源文件,也相对于 源文件所属的模块。

公共访问使实体能够 可在其定义模块的任何源文件中使用,也可在 来自导入定义模块的另一个模块的源文件。 指定公共接口时通常使用公共访问 到一个框架。

内部访问使实体可以在任何 来自其定义模块的源文件,但不在任何源文件中 在该模块之外。您通常在以下情况下使用内部访问 定义应用或框架的内部结构。

私人访问 将实体的使用限制在其自己的定义源文件中。采用 私有访问以隐藏特定部分的实现细节 的功能。公共访问权限最高(限制最少) 访问级别和私有访问是最低的(或最严格的) 访问级别。

【讨论】:

以上是关于Swift 中的数据封装的主要内容,如果未能解决你的问题,请参考以下文章

Swift 运用协议泛型封装网络层

iOS(Swift) 基于 Moya 的二次封装

Alamofire的简单封装

Swift3.0封装 AFN 的 GET&POST网络请求

iOS开发之资讯类App常用分类控件的封装与实现(CollectionView+Swift3.0+)

6 面向对象中的封装