为什么Swift BooleanLiteralConvertible需要一个布尔文字?

时间:2016-04-08 18:23:55

标签: swift

我正在尝试向我的类添加BooleanLiteralConvertible支持,以便我可以使用布尔值实例化它。抛弃循环的东西是布尔值和布尔文字之间的区别。

例如,在添加协议后我尝试了这个:

func setSelected(value: Bool) {
    var node: MyClass = value
}

但Swift抱怨它无法将Bool转换为MyClass。我花了一段时间才意识到它必须是一个布尔文字。奇怪的是,以下工作正常:

func setSelected(value: Bool) {
    var node: MyClass = value ? true : false
}

......这对我来说似乎太傻了。这个看似非常离奇的要求是否有正当理由?

2 个答案:

答案 0 :(得分:6)

符合BooleanLiteralConvertible的类型可以使用布尔文字 truefalse初始化,例如

let mc : MyClass = true

这与使用布尔值初始化类型无关:

let value : Bool = // ... some boolean value
let mc : MyClass = value // error: cannot convert value of type 'Bool' to specified type 'MyClass'

并且 - 据我所知 - 没有办法做出这样的暗示 转换工作。您必须编写自定义init方法

init(bool : Bool) {
    // ...
}

并将对象初始化为

let value : Bool = // ... some boolean value
let mc = MyClass(bool: value)

答案 1 :(得分:2)

我喜欢这个问题。只有Swift团队可以肯定地回答,但我可以推测为什么:将类型值转换为不同类型的变量而不进行显式转换或转换很容易与程序员错误混淆,并且在很多情况下是编译器应警告。

示例(并假设Person也是StringLiteralConvertible,可以使用字符串变量以及您在问题中提出的文字来初始化:

struct Person {

    private static var idCounter = 1

    var name:String
    let id:Int

    init(withName name:String) {
        Person.idCounter += 1
        self.name = name
        self.id = Person.idCounter
    }
}

var person = Person(withName:"Mary")
let name = "John"
person = name

上面的代码看起来很像一个错误,程序员正在为类型为String的变量分配错误类型(Person)的值。实际上它可能错误。也许程序员只是想更改人员的{em>名称(person.name = name)而不创建具有新唯一ID的新Person。或者程序员可能会为person分配一些其他值,但会输入错误或代码完成错误。没有成为原始程序员,或仔细研究所有上下文,看看这种转换是否有意义,很难说。并且从最初初始化变量的位置进一步分配会变得更难如果编译器在此警告类型String的值被分配给Person类型的变量吗?

这个例子会更清晰,更符合Swift惯例:

var person = Person(withName:"Mary")
let name = "John"
person = Person(withName:name)

以上版本对于编译器和稍后阅读本文的任何其他程序员来说都是完全明确的。