2017-10-19 46 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