1

Right now I have the following classes:

class A {
    class func instantiate() -> A {
        return MakeObject()
    }
}

class B: A {}

let x = B.instantiate()

This results in x being of type A. How can I change instantiate in order to return an instance of the subclass that was called from? In other words, so that x ends up being of type B.

EDIT:

This is what I used to solve it, based on Martin R's answers:

class A {
    class func instantiate() -> Self {
        func helper<T>() -> T {
            return MakeObject() as! T
        }

        return helper()
    }
}
Nick Keets
  • 3,240
  • 1
  • 14
  • 13

1 Answers1

4

The returns type needs to be Self (which is the concrete type when the class method is called), and initialization must be done with a required init method (which can be overridden in a subclass):

class A {

    class func instantiate() -> Self {
        return self.init()
    }

    required init() {

    }
}

class B: A {}

let x = B.instantiate() // `x` has type `B`

Alternatively, just define an init method

init(parameters ...) {

}

which "automatically" returns instances of the class that is is called on.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • It may well be that this solution has been given before, but I haven't found an exact duplicate yet. Please let me know if this is a duplicate, then I'll delete the answer and link to the existing answer instead. – Martin R Dec 10 '15 at 14:46
  • even thought it could be a duplicate, i like you answer. it is very useful! – user3441734 Dec 10 '15 at 18:01
  • Thanks, this is useful. How about if I wanted to return an object without using `init` though (e.g. from a cache)? Using something like `return obj as! Self` is not allowed. – Nick Keets Dec 11 '15 at 10:00
  • 1
    @NickKeets: The approach from http://stackoverflow.com/a/31167323/1187415 might work. – Martin R Dec 11 '15 at 10:04