2015-04-28 4 views
0

Я хочу использовать typealias для функции, которая используется в универсальном классе. Один из параметров функции использует общий тип класса. Это упрощенный пример:Как использовать параметр типа в typealias?

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 ...

(Swift 1,2)

ответ

1

Написав

class TestGeneric<T: Bar> 

все, что вы действительно сделали это определить T универсально как типа бара, когда используется внутри метода, так что вы можете написать это:

func myFunc(aValue:T) { 

} 

вместо этого:

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

    } 

каждый время, которое вы хотите определить T как тип Bar.

Если вы хотите, чтобы класс был общим, вы используете только <T>, например: class TestGeneric<T> и тип определяется при инициализации.

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())) 
+0

Мне нужно, чтобы класс был общим и ограничивал тип класса Bar (isA), поэтому я использую ''. То, что мне не хватало, было этой маленькой вещью: объявить функцию как тип 'TestTypealias .MyFuncGeneric' вместо' TestTypealias.MyFuncGeneric'. Это также объясняет, почему моя упрощенная версия кода Грегцо работает, он просто не указал тип, и компилятор делает это правильно. Благодаря! – Ixx

1

Это компилирует и ведет себя, как и ожидалось:

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) 
} 
+0

Также работает с добавленным предложением where, только что отмеченным. – Gregzo

+0

Я уменьшил ваш пример до наименьшей разницы с моим и выяснил, что причиной ошибки компилятора является объявление типа функции! поэтому, если я напишу 'let myFunc2 = {(bar: Bar) в , верните« привет » }' вместо 'let myFunc2: TestTypealias.MyFuncGeneric = {(bar: Bar) в return" hello " }' он компилируется ... – Ixx

Смежные вопросы