Swift Generics

Swift Generics

首先来思考一下下面的一个例子:

 struct Buffer {
  
  var count: Int
  
  subscript(at: Int) -> Int {
    get { return 1 }
  }
  
}
复制代码

我们实例完一个Buffer对象,然后呢,就可以通过下标来找到对应的值了,看起来没毛病,但是呢,如果需要构建一个String类型的Buffer咋办呢。暴力点的办法是,定义一个StringBuffer,然后把上面的代码copy一份,把下标的返回值设置为String.

struct StringBuffer {

  var count: Int
  
  subscript(at: Int) -> String {
    get { return "1" }
  }
  
}
复制代码

但这样很蠢有没有,譬如,我如果要一个DoubleBuffer咋办呢,再copy&paste?显然不合适啊。这时,我开了个脑洞,我把返回值设成Any不就啥事都没了?

struct AnyBuffer {
  var array: [Any]
  
  var count: Int {
    get { return array.count }
  }
  
  init(array: [Any]) {
    self.array = array
  }
  
  subscript(_ index: Int) -> Any {
    get { return self.array[index] }
    set { self.array[index] = newValue }
  }
}
复制代码

这样不管是什么Int, Double还是String都可以包装进去而不报错。但是新的问题又来了,那就是解包的时候容易出问题,譬如:

var words: AnyBuffer = AnyBuffer(array: ["12", "34", 56])
words[0] = 42
print(words)
let word = words[2] as! String
print(word)
复制代码

这里就会报一个:

Could not cast value of type 'Swift.Int' (0x100532750) to 'Swift.String' (0x100534888).
复制代码

的error。

因此swift的Any跟OC的运行时一样,有很多的不确定性,因此应该尽量避免这种运行时的特性,而是回归到静态,即编译时就能把问题给找到。

使用Any还有个弊端就是,会极大程度的浪费内存,因为我不知道你需要多少的内存,所以我会尽可能多的给你分配足够大的内存空间,但你却用来存Bool。

总结:
1. 使用Any,容易引起crash,徒增不确定性
2. 浪费内存
复制代码

接着就引入了泛型的概念。

泛型

上面的例子用泛型来定义的话,就是这个样子:

struct Buffer<Element> {
  var array: [Element]
  
  var count: Int {
    get { return array.count }
  }
  
  init(array: [Element]) {
    self.array = array
  }
  
  subscript(_ index: Int) -> Element {
    get { return self.array[index] }
    set { self.array[index] = newValue }
  }
}

// Cannot convert value of type 'Buffer<Any>' to specified type 'Buffer<String>'
var buffers: Buffer<String> = Buffer(array: ["12", 34])

// Cannot assign value of type 'Double' to type 'String'
buffers[1] = 123.34
复制代码

你看,这样在编译时,就能把crash扼杀在摇篮里,而且内存的分配上也更加的紧凑一些。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值