2017-10-19 43 views
2

我發現Swift類在調用類型向下轉換時不能調用原始方法。類型向下找不到原始方法在Swift中

AFAIK,同樣的事情可以通過類指針在C/C++中完成。

讓代碼會談:

protocol MyProtocol { 
    func log() 
} 

class MyClass: MyProtocol { 
} 

class MyGenericClass<T>{ 
    init(_ t: T) {} 
} 

extension MyGenericClass: MyProtocol { 
    func log() { 
     print("MyGenericClass MyProtocol") 
    } 
} 

extension MyGenericClass where T==Int { 
    func log() { 
     print("MyGenericClass<Int>") 
    } 
} 

extension MyProtocol { 
    func log() { 
     print("MyProtocol") 
    } 
} 
extension MyProtocol where Self==TestSwift.MyGenericClass<Int> { 
    func log() { 
     print("MyProtocol where MyGenericClass<Int>") 
    } 
} 

extension MyProtocol where Self==MyClass { 
    func log() { 
     print("MyProtocol where MyClass") 
    } 
} 

func logByProtocol(_ p: MyProtocol) { 
    p.log() 
    print("Type of p is: \(type(of: p))") 
} 

let myGenericClassNumber = MyGenericClass(1) 
let myGenericClassString = MyGenericClass("1") 
let myClass = MyClass() 


myGenericClassNumber.log()//expect "MyGenericClass<Int>" 
myGenericClassString.log()//expect "MyGenericClass MyProtocol" 
myClass.log()//expect "MyProtocol where MyClass" 

logByProtocol(myGenericClassNumber)//expect "MyGenericClass<Int>", BUT "MyGenericClass MyProtocol" 
logByProtocol(myGenericClassString)//expect "MyGenericClass MyProtocol" 
logByProtocol(myClass)//expect "MyProtocol where MyClass" 

我希望logByProtocol(myGenericClassNumber)將打印"MyGenericClass<Int>",但它打印 「MyGenericClass MyProtocol」。

看來,MyGenericClass<Int>找不到原始log()方法,而將類型向下轉換爲MyProtocol

如何解決這個問題使"down"類可以調用它的原始方法?

+0

已解決。只需添加'如果p是MyGenericClass {(p as!MyGenericClass ).log()}'。 –

+0

你必須編寫儘可能多的泛型,如字符串泛型,雙泛型,浮泛型等。這不是解決方案,它的破解! – D4ttatraya

回答

0

這是發生,因爲Swift dynamic dispatch是忽略這個通用的限制:

MyGenericClass where T==Int 

,並在此擴展調度電話:

extension MyGenericClass: MyProtocol {} 

動態分配我說的是你已經寫logByProtocol(_)方法;它使用動態調度來調用log()方法。

爲什麼這個

myGenericClassNumber.log() 

工作正常,是因爲它是靜態的MyGenericClass<Int>對象調度log()方法。

+1

這解釋了行爲,但沒有回答作者的問題。 – user28434