Skip to content

Instantly share code, notes, and snippets.

@koleson
Last active January 29, 2016 20:47
Show Gist options
  • Save koleson/6782d9d05931f1a06f2f to your computer and use it in GitHub Desktop.
Save koleson/6782d9d05931f1a06f2f to your computer and use it in GitHub Desktop.
Confusion: Method overrides in extensions
// Playground - unexpected extension method selection
import Foundation
var str = "Hello, playground"
protocol MethodProtocol {
func aMethod() -> String
}
class Base : NSObject {
required override init() {
// nothing, but we must have this intializer to init from a .Type object
}
func aMethod() -> String {
return "called the base aMethod"
}
func anotherMethod() -> String {
return "called the base anotherMethod"
}
}
class Subclass : Base {
// we'll override aMethod in the extension
override func anotherMethod() -> String {
return "called the subclass anotherMethod"
}
}
extension Subclass {
override func aMethod() -> String {
return "called the subclass aMethod"
}
}
var arrayOfClasses = Array<Base.Type>()
arrayOfClasses.append(Subclass.self)
var baseObj = Base()
baseObj.aMethod() // returns "called the base method" - expected
var subclassObj = Subclass()
subclassObj.aMethod() // returns "called the subclass method" - expected
var subclassType = Subclass.self
var subclassObjInstantiatedFromType = subclassType.init()
subclassObjInstantiatedFromType.aMethod() // returns "called the subclass method" - expected
var subclassObjInstantiatedFromArrayType = arrayOfClasses[0].init() // inferred type: Base
let dynamicTypeOfObjInstantiatedFromArrayType = subclassObjInstantiatedFromArrayType.dynamicType // returns Subclass.Type - expected
subclassObjInstantiatedFromArrayType.aMethod() // returns "called the base method" - wat?
subclassObjInstantiatedFromArrayType.anotherMethod() // returns "called the subclass anotherMethod" - better, but... wat?
if let subclassObjAsSubclass = subclassObjInstantiatedFromArrayType as? Subclass {
subclassObjAsSubclass.aMethod() // returns "called the subclass method" - expected
}
// so clearly the inferred type of the variable impacts method dispatch. but how do we
// dynamically type the variable based on the object's concrete type?
// we want to avoid any references to the concrete type at compile-time.
// the "if let ... as? ..." construct requires a compile-time type, so it won't work.
// this illustrates the problem more succinctly, the above is just a contrived
// example of what we can see here.
var subclassObjAsBase: Base = Subclass()
subclassObjAsBase.aMethod() // returns "called the base aMethod" - hmm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment