protocol ValuePrinter { func print(_ x: Int) func print(_ x: String) } protocol IntOrString { func asInt() -> Int? func asString() -> String? } extension Int : IntOrString { func asInt() -> Int? { return self } func asString() -> String? { return nil } } extension String : IntOrString { func asInt() -> Int? { return nil } func asString() -> String? { return self } } class OmniValuePrinter : ValuePrinter { // oneshot double override! func print<X: IntOrString>(_ x: X) { if let i = x.asInt() { Swift.print(i) } if let s = x.asString() { Swift.print(s) } } } let printer = OmniValuePrinter() as ValuePrinter printer.print(3) printer.print("a")