类型检查运算符(是)用于检查与同源协议:为什么可以对选项进行此操作?

时间:2016-07-02 12:10:38

标签: swift

TL; DR

  • 为什么我们允许使用类型检查运算符is对同源协议(本身可能不会用作类型)用于可选的实例,当这是(正如预期的那样)时不允许非可选类型的实例?

背景

我们可以使用类型检查运算符(is)来检查实例是否属于某种类型,例如

let a = 1
a is Int    // true
a is String // false

另外,同源协议(具有Self的协议或相关类型要求)不能用作具体类型,例如

protocol Homogenous {
    func foo(_: Self)
}

let b: Homogenous? = nil
    /* error: protocol 'Homogenous' can only be used as a generic constraint 
              because it has Self or associated type requirements            */

因此,很自然我们不能使用类型检查运算符is来检查实例是否是同类协议" type"。与此假设一致,以下示例按预期失败

protocol Homogenous {
    func foo(_: Self)
}

extension Homogenous {
    func foo(_: Self) {}
}

extension Int: Homogenous {}

let a: Int = 1

a is Homogenous
    /* error: protocol 'Homogenous' can only be used as a generic constraint 
              because it has Self or associated type requirements            */

问题

this answer的讨论中,有人注意到 - 特殊情况 - 我们允许使用类型检查运算符is对同类协议进行类型检查(如果实例我们是&#39} ;重新检查是可选的。

protocol Homogenous {
    func foo(_: Self)
}

extension Homogenous {
    func foo(_: Self) {}
}

class Foo: Homogenous {}
extension Int: Homogenous {}

let a: Int = 1
let b: String = "one"
let c: Foo = Foo()

/* Generally, we can't type check using 'is' against a homogenous protocol,
   but if the variable we are type checking is an optional, we can.
   Why is this?                                                             */
let bar: Int? = a
bar is Homogenous         // true
Optional(a) is Homogenous // true

let baz: String? = b
baz is Homogenous         // false

let bax: Foo? = c
bax is Homogenous         // true

问题:

  • 为什么我们允许is对可选的实例使用同源协议?

我可能会补充说,我们无法使用简单的枚举包装器来模拟此行为

enum Wrapper<T> {
    case Some(T)
    case None
}

let a: Int = 1
let foo = Wrapper.Some(a)
foo is Homogenous
    /* error: protocol 'Homogenous' can only ... */

0 个答案:

没有答案