通用方法重写不在swift中工作
有一个来自第三方的协议Printable和一个结构打印机。
protocol Printable {}
struct Printer {
    static func print<T>(object: T) -> String {
        return "T"
    }
    static func print<T: Printable>(object: T) -> String {
        return "Printable"
    }
}
现在我正在制作一个通用的
struct Generic<T> {
    var args: T
    func display() {
        print(Printer.print(args))
    }
}
和两个结构
struct Obj {}
struct PrintableObj: Printable {}
var obj = Generic(args: Obj())
var printableObj = Generic(args: PrintableObj())
当我在他们两个上调用显示功能时。
obj.display()
显示T
printableObj.display()
显示T但我希望它打印“可打印”
我能想到的一种解决方案是有两种不同的泛型
struct Generic<T>
struct PrintableGeneric<T: Printable>
是否有其他解决方案,而不更改Printable协议和打印机结构。
是。 但答案有点奇怪。 第一部分有一定的道理; 第二部分是完全怪异的。 我们来看看它。
struct Generic<T> {
    var args: T
    func display() {
        print(Printer.print(args))
    }
}
  选择print的正确重载是在编译时决定的,而不是运行时决定的。  这是最让人混淆的东西。  他们希望像JavaScript那样处理Swift,其中一切都是动态的。  Swift喜欢静态,因为它可以确保你的类型是正确的,它可以做很多优化(Swift喜欢编译器优化)。  那么,编译时间, args是什么类型?  那么,这是T  T是否已知可Printable ?  不它不是。  所以它使用非Printable版本。 
  但是,当Swift使用PrintableObj专门化Generic时,它不知道它是Printable吗?  编译器能否在此时创建不同版本的display ?  是的,如果我们知道在编译时每个调用者都会存在这个函数,并且他们都不会被扩展为Printable (这可能发生在一个完全不同的模块中)。  如果不创建很多奇怪的角落案例(例如,内部事物的行为与公共事物不同),并且不强制Swift主动生成未来呼叫者可能需要的每种可能的display版本,都很难解决这个问题。  斯威夫特可能会及时改善,但我认为这是一个难题。  (Swift已经遭受了一些性能下降,所以公共泛型可以专门化,而无需访问原始源代码,这会使问题变得更加复杂。) 
  好的,所以我们明白了。  T不是Printable 。  但是如果我们有一个明确的Printable类型,那么我们在编译时就知道并且存在于这个函数中呢?  那么它会起作用吗? 
func display() {
    if let p = args as? Printable {
        print(Printer.print(p))
    } else {
        print(Printer.print(args))
    }
}
  哦,那么近......但不完全。  这几乎可行。  if-let实际上完全是你想要的。  p被分配。  它是Printable 。  但它仍然称为非打印功能。  ?!?!?!?! 
  这个地方我个人认为Swift目前刚刚破解,希望能够修复。  它甚至可能是一个错误。  问题是Printable本身不符合Printable 。  是的,我也不明白,但是你去了。  所以我们需要做一些符合Printable东西来获得正确的过载。  像往常一样,输入橡皮擦救援。 
struct AnyPrintable: Printable {
    let value: Printable
}
struct Generic<T> {
    var args: T
    func display() {
        if let p = args as? Printable {
            print(Printer.print(AnyPrintable(value: p)))
        } else {
            print(Printer.print(args))
        }
    }
}
  这将打印你想要的方式。  (假设Printable需要一些方法,您只需将这些方法添加到AnyPrintable类型橡皮擦。) 
  当然,正确的答案并不是在Printer以这种方式使用泛型重载。  这只是太混乱和脆弱的方式。  它看起来很不错,但它一直在爆炸。 
static func print<T>(object: T) -> String {
    if object is Printable {
        return "Printable"
    } else {
        return "T"
    }
}
在我看来,唯一的选择是 - 在“print()”函数中使用if-else进行类型转换
static func print<T>(object: T) -> String {
    if let _ = object as? Printable {
        return "Printable"
    }
    return "T"
}
或非通用变体
static func print(object: Any) -> String {
    if let _ = object as? Printable {
        return "Printable"
    }
    return "T"
}
                        链接地址: http://www.djcxy.com/p/90423.html
                        
                        
                    