Tag: Typeerasure

类型擦除

下标不知道要打什么 前情提要 会想要打这篇是因为因为最近在看ReSwift跟Redux时发现ReSwift的源代码中有很多AnySubscriber,AnySubscription,SubscriptionBox之类奇怪的型态,而仔细看的话可以发现这些型态下面也有Subscriber,Subscription之类没有任何的型态。而造成的原因是什么呢?在解释前我们先来看一下例子吧! 会想要打这篇的另外一个原因是因为之前有看到跟Type Erasure有关的文章,但当时的我不太了解为什么要这样做,而最近看ReSwift时实在看太多type Erase了,于是决定把它搞懂。 先看个例子 只能这样了吗? 不,我才不要这样就放弃呢。 那我们只好把Pokemon这个形态给藏起来,不让swift编译器发现我们在干不法勾当。 如果我们不能使用Pokemon protocol当类型态,那我们能不能使用class将它包起来呢?可以!但应该怎么做呢?其实你在写swift时应有发现些东西叫做AnySequence,AnyIterator等等的东西,其实你仔细想想,Sequence是个协议,他不能当作型态使用,但有时我们在宣告阵列时他会是AnySequence型态。翻找一下swift源代码可以发现apple在实作这些wrapper的思路与实作方式,我们来看一下apple怎么写: ///一个类型擦除的序列。 /// ///`AnySequence`的实例将其操作转发到基础数据库 ///具有相同“元素”类型的序列,隐藏了 ///基础序列。 // @ _ versioned @_fixed_layout 公共结构AnySequence :序列{ ///创建一个新的序列,该序列将操作包装并转发到`base`。 @_inlineable public init (_ base:S) 哪里 S.Element ==元素{ self._box = _SequenceBox(_base:基本) … } 可以看到AnySequence是把Sequence的操作进一步的拉出来的wrapper而已。我们需要做的事是做个init,并且检查Sequence中的Element跟初始化时的S.Element是否为同一型态,然后把操作拉出来即可(apple使用另一层wrapper:box把比较杂乱的代码藏起来了,打开AnySequenceBox可以看到进一步的实作)。 那我们现在也来做一样的事吧: 抓到法律的突破后,我们就有了看似真的AnyPokemon型态了,于是我们很开心的把神奇宝贝农场改成: let pokemonRanch:[AnyPokemon] = [] 但别忘记AnyPokemon也算是某种程度的泛型型态,我们必须告诉他Power是什么: let pokemonRanch:[AnyPokemon ] = [] OK,这样写就没有error了。 但我们应该怎么把神奇宝贝放进去呢呢? let pokemon牧场:[AnyPokemon […]