如何在Swift中编写一个通用函数来执行条件向下转换?

如何在Swift中编写一个通用函数来执行条件向下转换?,swift,generics,functional-programming,Swift,Generics,Functional Programming,我的目标是编写一些东西,可以将类似[AnyObject]的东西转换为结果,以便在使用混合的Swift/Obj-C代码库时轻松进行安全和可链接的强制转换。条件下行操作符as?似乎很好地支持这一点,但我无法让一个通用函数利用这种行为工作。我将遇到的问题简化如下: class A { } let obj = A() let array: [AnyObject] = [obj] func cast<T, U>(x: T, type: U.Type) -> U? { if

我的目标是编写一些东西,可以将类似
[AnyObject]
的东西转换为
结果
,以便在使用混合的Swift/Obj-C代码库时轻松进行安全和可链接的强制转换。条件下行操作符
as?
似乎很好地支持这一点,但我无法让一个通用函数利用这种行为工作。我将遇到的问题简化如下:

class A { }

let obj = A()

let array: [AnyObject] = [obj]

func cast<T, U>(x: T, type: U.Type) -> U? {
    if let x = x as? U {
        return x
    } else {
        return nil
    }
}

// This works
if let array = array as? [A] {
    println(array)
}

// This works
println(cast(obj, A.self))

// This doesn't
println(cast(array, [A].self))
class A{}
设obj=A()
let数组:[AnyObject]=[obj]
func cast(x:T,type:U.type)->U?{
如果设x=x为?U{
返回x
}否则{
归零
}
}
//这很有效
如果让数组=数组为?[A]{
println(数组)
}
//这很有效
println(演员阵容(obj,A.self))
//这并不重要
println(强制转换(数组[A].self))

注意:这在Swift 2.0中有效,我不知道1.2,试试看

如果您想执行类似操作,您必须使用一个用于
SequenceType
s的方法重载
cast
方法:

func cast<T : SequenceType, U : SequenceType>(x: T, type: U.Type) -> [U.Generator.Element]? {
    let y = x.map{ $0 as? U.Generator.Element }
    if y.contains({ $0 == nil }) {
        return nil
    } else {
        return y.flatMap{ $0 }   // Swift 1.2 : y.map{ $0! }
    }
}
func cast(x:T,type:U.type)->[U.Generator.Element]?{
设y=x.map{$0as?U.Generator.Element}
如果y.contains({$0==nil}){
归零
}否则{
返回y.flatMap{$0}//Swift 1.2:y.map{$0!}
}
}

编辑:根据您的编辑进行更改

通常,Swift不支持
GenericType as?GenericType
cast,即使
B
a
的子类型<代码>数组作为?数组只是为了方便起见的一个例外

有一个未记录的内部内置函数:

func _arrayConditionalDownCastElements<SourceElement, TargetElement>(a: Array<SourceElement>) -> [TargetElement]?
func cast<T,U>(x:T, _: U.Type) -> U? {
    return x as? U
}

func cast<T,U>(x:[T], _: [U].Type) -> [U]? {
   return _arrayConditionalCast(x)
}
类似地,对于
字典
集合
,分别有
\u dictionarydowncastcomative和
\u setdowncastcomative

func _dictionaryDownCastConditional<BaseKey, BaseValue, DerivedKey, DerivedValue>(source: Dictionary<BaseKey, BaseValue>) -> Dictionary<DerivedKey, DerivedValue>?
func _setDownCastConditional<BaseValue, DerivedValue>(source: Set<BaseValue>) -> Set<DerivedValue>?
func\u dictionaryDownCastConditional(来源:Dictionary)->字典?
func\u setDownCastConditional(源:Set)->Set?
使用此选项:

func cast<TKey,TValue, UKey, UValue>(x:[TKey: TValue], _: [UKey:UValue].Type) -> [UKey: UValue]? {
    return _dictionaryDownCastConditional(x)
}

func cast<T, U>(x: Set<T>, _: Set<U>.Type) -> Set<U>? {
    return _setDownCastConditional(x)
}
func cast(x:[TKey:TValue],[UKey:UValue].Type)->[UKey:UValue]?{
返回_dictionaryDownCastConditional(x)
}
func cast(x:Set,u:Set.Type)->Set?{
返回_setDownCastConditional(x)
}

同样,它们是未记录的。使用它们的风险由您自己承担:)

对不起,我似乎过于简化了我的示例。虽然这对返回Bool有效,但我的实际最终目标是获得强制类型或错误,我看不到通过专门化SequenceType函数来实现这一点的方法,因为我仍然无法强制转换结果。我将更新我的示例代码以使其更清晰。@RayLillywhite我不明白为什么这不起作用,我更新了我的答案。也许你的问题还是太简单了?哦,对不起,函数签名中有一个错误的返回类型。问题是,如果条件向下转换成功,我需要能够返回强制转换的值。