【问题标题】:How to use type parameter in typealias?如何在 typealias 中使用类型参数?
【发布时间】:2015-04-28 10:22:50
【问题描述】:

我想为泛型类中使用的函数使用类型别名。该函数的参数之一使用类的泛型类型。这是一个简化的例子:

class Bar {}

// no typealias - works
class TestGeneric<T: Bar> {
    let myFunc: (T) -> String

    init(myFunc: (T) -> String) {
        self.myFunc = myFunc
    }
}

let myFunc: (Bar) -> String = {(bar: Bar) in
    return "hello"
}

let test = TestGeneric<Bar>(myFunc: myFunc)
println(test.myFunc(Bar()))

// typealias - doesn't compile
class TestTypealias<T: Bar> {
    typealias MyFuncGeneric = (T) -> String

    let myFunc: MyFuncGeneric

    init(myFunc: MyFuncGeneric) {
        self.myFunc = myFunc
    }
}

let myFunc2: TestTypealias.MyFuncGeneric = {(bar: Bar) in
    return "hello"
}

let test2 = TestTypealias<Bar>(myFunc: myFunc2) // Error: Cannot invoke initializer for type 'TestTypealias<Bar>' with an argument list of type '(myFunc: T -> String)'
println(test2.myFunc(Bar()))

有没有办法解决这个问题?还是在使用泛型时我必须放弃 typealias?在实际代码中我有很多参数,确实需要一个类型别名...

(斯威夫特 1.2)

【问题讨论】:

    标签: swift generics type-alias


    【解决方案1】:

    通过写作

    class TestGeneric<T: Bar> 
    

    您真正所做的只是在方法内部使用时将 T 普遍定义为 Bar 类型,因此您可以这样写:

    func myFunc(aValue:T) {
    
    }
    

    而不是这个:

    func myFunc<T: Bar>(aValue:T) {
    
        }
    

    每次您想将 T 定义为 Bar 类型时。

    如果您希望类本身是通用的,则仅使用&lt;T&gt;,例如:class TestGeneric&lt;T&gt;,并且类型在初始化时定义。

    class Bar {}
    
    // no typealias - works
    class TestGeneric<T> {
        let myFunc: (T) -> String
    
        init(myFunc: (T) -> String) {
            self.myFunc = myFunc
        }
    }
    
    let myFunc: Bar -> String = {(bar: Bar) in
        return "hello"
    }
    
    let test = TestGeneric<Bar>(myFunc: myFunc)
    println(test.myFunc(Bar()))
    
    // typealias - doesn't compile
    class TestTypealias<T> {
        typealias MyFuncGeneric = T -> String
        func myFunc(aValue:T) {
    
        }
        let myFunc: MyFuncGeneric
    
        init(myFunc: MyFuncGeneric) {
    
            self.myFunc = myFunc
        }
    }
    
    let myFunc2: TestTypealias<Bar>.MyFuncGeneric = {(bar: Bar) in
        return "hello"
    }
    
    let test2 = TestTypealias<Bar>(myFunc: myFunc2)   
    println(test2.myFunc(Bar()))
    

    【讨论】:

    • 我需要类是通用的,并将类型限制为类 Bar (isA),这就是我使用 &lt;T: Bar&gt; 的原因。我缺少的是这个小东西:将函数声明为类型TestTypealias&lt;Bar&gt;.MyFuncGeneric 而不是TestTypealias.MyFuncGeneric。这也解释了为什么我的 Gregzo 代码的简化版本有效,他只是没有指定类型,编译器会正确推断它。谢谢!
    【解决方案2】:

    这编译并按预期运行:

    class Test< T >
    {
        typealias GenFunc = ( thing: T ) -> Void
    
        let thing : T
    
        init( thing: T )
        {
            self.thing = thing
        }
    
        func ExecuteFunc( genFunc: GenFunc )
        {
            genFunc( thing: self.thing )
        }
    }
    

    用途:

    let t = Test( thing: "blah" )
    
    t.ExecuteFunc()
    { ( thing: String ) -> Void in
        println( thing )
    }
    

    【讨论】:

    • 我将您的示例缩小到与我的最小差异并发现,导致编译器错误的原因是函数的类型声明!所以如果我写 let myFunc2 = {(bar: Bar) in return "hello" } 而不是 let myFunc2: TestTypealias.MyFuncGeneric = {(bar: Bar) in return "hello" } 它编译...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    相关资源
    最近更新 更多