分配关联类型的元组,为什么只允许通过显式的逐个成员分配? (错误:无法表达元组转换)

时间:2016-02-02 15:15:14

标签: swift tuples

当将Int成员的元组分配给Int符合的(异构)协议类型的元组时,似乎只允许通过显式成员执行此赋值成员分配。

protocol MyType {}
extension Int: MyType {}

let intPair = (1, 2)
var myTypePair : (MyType, MyType)

// OK
myTypePair = (intPair.0, intPair.1)

// OK
let intPairToMyTypePair : ((Int, Int)) -> (MyType, MyType) = { ($0.0, $0.1) }
myTypePair = intPairToMyTypePair(intPair)

// For all below: 
// "Error: cannot express tuple conversion '(Int, Int)' to '(MyType, MyType)'"
myTypePair = intPair
myTypePair = (intPair as! (MyType, MyType))
    /* warning: forced cast from '(Int, Int)' to '(MyType, MyType)' 
                always succeeds <-- well, not really */

if let _ = intPair as? (MyType, MyType) { }
    /* warning: conditional cast from '(Int, Int)' to '(MyType, MyType)' 
                always succeeds */

特性是对于上面的转换案例,Swift编译器警告

  

警告:来自'(Int, Int)'的强制/有条件投射   到'(MyType, MyType)' 总是成功

它显然没有:

  

错误:无法表达元组转换'(Int, Int)'   到'(MyType, MyType)'

问题:这里的问题是,是否按预期不允许直接分配?如果是这样,那么怎么了警告信息,铸件将永远成功?

(编辑添加)

进一步澄清我在这里提出的特殊行为:我想知道为什么即使Swift警告我们"bar"

,以下代码片段也会打印'is' case is always true
let intPair = (1, 2)

switch intPair {
case is (MyType, MyType): print("foo") /* warning: 'is' test is always true */
case _ : print("bar")
}
    // "bar"

数组的类似情况很简单,有解释错误,但我不知道这是否是一个有效的比较,因为元组更多是匿名结构,而不是Array的某些堂兄。

let intArr = [Int](1...5)
var myTypeArr : [MyType]

myTypeArr = intArr
    /* error: cannot assign value of type '[Int]' to type '[MyType]' */

if let _ = intArr as? [MyType] { }
    /* error: 'MyType' is not a subtype of 'Int' */

2 个答案:

答案 0 :(得分:0)

在这种情况下警告为真,因为intPair是(Int,Int),它符合(MyType,MyType)。所以演员阵容将永远成功。由于强类型检查,编译器知道此特定实例将始终成功。

为什么myTypePair = intPair错误是因为myTypePair比intPair更通用,更具体。因此类型不匹配,因此无法分配。

答案 1 :(得分:0)

我刚刚对类型的Swift进行了测试。我想我可能会帮助Array部分。但我所有的答案都是基于我的测试我个人的理解。

您在代码中使用的所有类型都是Swift类型,与Objective-C桥无关。在这种情况下,Swift的行为与Java类似。检查下面的Java代码:

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<B> b = new ArrayList<B>();
        ArrayList<A> a = b; // compile error: incompatible types: java.util.ArrayList<B> cannot be converted to java.util.ArrayList<A>
    }
}
class A {
}
class B extends A {
}

您可以查看此answer的评论。我认为swift用 Swift Value Type 的原因相同。

请注意,我会重点介绍Value Type。因为对于Class Type,事情发生了变化。检查下面的快速代码:

class A {}
let a = [A()]
let o: [AnyObject] = a // there is no problem for this!

实际上,所有继承自AnyObject或具有@objc属性的类都将使用NSArray来处理。您可以查看swift document了解更多详情。

希望这可以提供帮助,如果您发现任何错误,请纠正我!