抹掉你的恐惧,牌擦拭就在这里

188bet金宝搏官网Okcupid正在为iOS招聘点击这里了解更多

介绍

在Okcupid188bet金宝搏官网,我们不断努力在课堂上施舍中最佳地实现。其中一个概念是类型擦除。你可能会想到自己“我从来没有在我的生活中使用类型擦除......”但你错了!你知道,AnyObject.实际上是一种删除混凝土类型的协议任何对象。你可能已经看到了任何Prefix分散在Swift标准库周围(无论如何任何人奥尔博, 等等)。

这种强大的构造是一把双刃剑。一方面,由于所有课程都符合AnyObject.如果您需要使用未知类型,它将充当所有类型的通用包装器,这是一个可用的所有类型。另一方面,它消除了对SWIFT类型安全系统的依赖。他们没有理由称之为“安全”!知道您正在使用的对象的类型存在重要的好处,并且当您调用对类型未实现的方法时,我们对OLE'Object-C崩溃的崩溃崩溃了。

但可以有两个世界解决方案吗?在Okcupid188bet金宝搏官网,我们认为答案是一个响应的是的。我们可以采取型式擦除的力量,并将其应用于特定用例,以获得灵活收集的好处,仍然保持SWIFT的强大安全系统的刚性。

为说明,我们将一个示例项目放在一起,其中包括我们的应用程序的代码,为我们的对话视图控制器实现了专用形式的类型擦除。

https://github.com/188bet金宝搏官网okcupid/swift-type-erasure.

Ivborw0kggoaaaansuheugaabamaaaszcayaaaciwkb7aaabgmldq1bzukdcielfqzyxoty2ltiu-5

问题

对于此示例,我们将建立代表Okcupid iOS应用程序中对话的模型。188bet金宝搏官网

在为我们的对话屏幕构建模型层时,我们考虑了一些目标:

  1. 我们需要良好的抽象来支持未来的特征的持久性
  2. 该模型需要轻松咀嚼单元测试
  3. 该架构应该是可扩展的,以便我们根据需要扩展逻辑

创建简单结构是我们的第一种方法:

struct对话{let threinid:string让isunread:bool让记者:用户// ..等}

但是,我们很快意识到这种方法没有达到我们所有的目标。具体而言,这并没有给我们我们需要的可扩展性。例如,如果Okcupid是引入新188bet金宝搏官网的对话类型,我们需要重新推荐大量代码来支持它。

这些“未来”类型的一些示例可能是坚持不懈群化分泌融合等等,因为对话是一个具体结构,支持整个应用程序中的多种类型的对话需要一个重要的重构。

由于我们知道任何类型的对话都会共享相同的基本属性,让我们抽象使用协议的具体类型。

方向的方法

让我们创造谈话服务器,一个包含对话的所有共享属性的协议。

协议对话商务问题{var trimeId:string {get} var记者:userprotocol {get} var isunread:bool {get} // etc ..}

谈话服务器协议非常适合表达共享财产要求,但我们也希望在我们的对话中使用功能齐全。例如,我们需要一种方法来区分一个对话的谈话。幸运的是,Swift为我们提供了哈希布扎尔协议(继承自等等协议)为此目的。

我们想要的是单一的实施哈希布扎尔可以在当前和未来的具体实施中共享谈话服务器。但是,议定书不可能(谈话服务器)实施另一种协议(哈希布扎尔)。我们需要一个具体的类型

它可以通过使用通过使用该协议的默认实现在哪里延期声明,专门适用于具体类型:

扩展对话商标在哪里自我:hashable {func哈希(进入Hasher:Inout hasher){hasher.comnbine(threousid)} func isequalto(_其他:connabledationProcololocol) - > Bool {Guard让其他作为?自我{return false} returnid == returndconversation.threadid}静态func ==(lhs:self,rhs:self) - > bool {return lhs.isequalto(RHS)}}

这告诉编译器可以实现任何具体类型谈话服务器哈希布扎尔免费获得默认实施!这是极大的强大,因为它允许单一的中央实施哈希布扎尔在所有具体类型中谈话服务器

要使用它,我们需要做的就是创建一个具体类型:

struct对话:对话前ocol {var trimeId:string var对应者:userprotocol var iSunRead:Bool}

现在,使用我们的共享实施哈希布扎尔我们需要做的就是:

//这是魔法发生的地方✨扩展对话:hashable {}

现在我们有一个具体的对话结构自动获得我们的实施哈希布扎尔只需提供空白实现。

但是......这一切都很棒,直到我们试图存储我们的实例谈话服务器在SET ......毕竟,我们仍然希望使用抽象的类型来实现最终的Flexibilty。

var connableationset = set ()

编译器对我们大喊大叫......

错误:类型“ConversationProtocol”不符合协议“Hashable”

这是有道理的,因为协议无法实现协议。那么如何制作一套谈话服务器s?这是擦除类型的位置。

我们需要一种具体类型,符合Hashable才能存储在一组中。

struct AnyHashableConversation:ConnableationPropolocol {var ThreadID:String {return Conveachation.Threadid} Var对应者:UserProtocol {Return Conveeation.Correspondent} Var IsUnRead:Bool {Return Conveeation.IsunRead}私有Let对话:对话前ocol init(对话:ConnugationProtocol){self.conversation=对话}} //使用我们现有的Hashable实现扩展名为AnyHashableConversation:hashable {}

就是这样!现在我们可以创建一组任何对话类型,它将使用单个共享实现散列哈希布扎尔!!

让对话= SET ()

结论

协议与类型擦除相结合的使用是一种用于抽象许多具体类型中的常用功能的有用技术。它允许我们保留我们的代码LoSley耦合,可扩展,易于测试。您是否有使用类型擦除或其他抽象的经验来解决类似的问题?让我们留下你的想法,我们喜欢了解更多!

标题图像由:https://www.iteratorshq.com/blog/scala-compiler-phages-with-pictures/type-erasure/