2016-08-11 74 views
3

我在XCode 7.3.1上使用Swift 2.2並嘗試從另一個Generic函數調用Generic函數。Swift通用函數調用另一個通用函數

代碼

class Thing1 { 
    let variable: SomeProtocol 
    init<A: SomeProtocol>(variable: A) { 
      self.variable = variable 
      self.add1(self.variable) 
    } 

    func add1<A: SomeProtocol>(stuff: A) { 
      let thing: Thing2 = Thing2() 
      thing.add2(stuff) 
    } 

} 

class Thing2 { 
    func add2<A: SomeProtocol>(stuff: A) { 

    } 
} 

protocol SomeProtocol { } 


add1("a") // Cannot invoke 'add1' with an argument list of type '(String)' 
add1(4) // Cannot invoke 'add1' with an argument list of type '(Int)' 

我得到的錯誤。

'Cannot invoke add with an argument of list type '(Whatever type I used to call the function)'' 
+0

我清理了一下代碼。在一個操場上它編譯得很好,但是當你嘗試並調用'add1'時,它不會讓你。 –

+0

@CodyWeaver你可以請你發佈一個儘可能接近編譯的最小例子嗎?通過這種方式,我們都可以一致地進行測試,而無需拿出我們自己的'SomeProtocol','Thing'等實現。 – Alexander

+0

增加了代碼,使它更清楚發生了什麼。 –

回答

2

的問題是,abstract types in Swift don't necessarily conform to themselves - 因此你不能用一個SomeProtocol類型的事,作爲一個具體類型的東西,符合到SomeProtocol(這是你的add1泛型函數期望的參數)。因此

你的情況最簡單的辦法就是使用通用variable的說法,而不是variable屬性,因爲它是一個通用的,它的類型爲符合SomeProtocol一個具體的東西,因此它可以被傳遞到您的add1功能:

init<A: SomeProtocol>(variable: A) { 
    self.variable = variable 
    add1(variable) 
} 

但是爲了以後的路線,以防止這些類型的問題,你可能要考慮讓你的類通用的,假設你的variable財產應該是恆定的類型的整個特定的生命週期Thing1實例:

class Thing1<A:SomeProtocol> { 

    let variable: A 

    init(variable: A) { 
     self.variable = variable 
     add1(variable) 
    } 

    func add1(stuff: A) { 
     let thing = Thing2() 
     thing.add2(stuff) 
    } 
} 

或者,你可以重構你的代碼中使用抽象類型SomeProtocol,這將讓你與任何工作類型符合SomeProtocol(例如,允許你在不同Thing1情況不同variable類型的混合一個數組):

class Thing1 { 

    let variable: SomeProtocol 

    init(variable: SomeProtocol) { 
     self.variable = variable 
     add1(variable) 
    } 

    func add1(stuff: SomeProtocol) { 
     let thing = Thing2() 
     thing.add2(stuff) 
    } 
} 

class Thing2 { 
    func add2(stuff: SomeProtocol) { 

    } 
} 

雖然你應該始終注意,配備使用抽象類,see this great WWDC talk for more info額外的費用。

0

添加擴展StringInt和建設Thing1對象使得它的工作:

extension String: SomeProtocol{} 
extension Int: SomeProtocol{} 

Thing1(variable: "a").add1("a") 
Thing1(variable: 2).add1(4)