Nathan H
Nathan H

Reputation: 49371

Swift: Get current class from a static method

In Swift, let's say I want to add a static factory method that returns an instance:

class MyClass {
  static func getInstance() {
    return MyClass(someProperty);
  }
}

But what if I don't want to write the class name? Is there an equivalent of self but for static methods and properties?

Same idea if I want to call another static method from a static method:

class MyClass {
  static func prepare(){
    //Something
  }

  static func doIt() {
    MyClass.prepare();
  }
}

Can I do this without using MyClass explicitly?

Upvotes: 6

Views: 2230

Answers (4)

ThomasW
ThomasW

Reputation: 17317

You can create a factory method that doesn't reference the class, like this:

class MyClass {
    static func factory() -> Self {
        let instance = Self.init()
        // other init here
        return instance
    }
}

Upvotes: 0

RobbeR
RobbeR

Reputation: 485

You can define a Protocol and use the swift generics like this:

protocol Vehicle {
  init()
}

class MyVehicleFactory<T:Vehicle> {
  static func getInstance() -> T {
    return T()
  }
}

And the people who copied your code can do this:

class Car : Vehicle {
  required init() { }
}
let car = MyVehicleFactory<Car>.getInstance();

Upvotes: 0

dfrib
dfrib

Reputation: 73186

As RobberR writes above, you could just use self for accessing static function of self, and self.init(...) for your factory example. Note that you still must specify MyClass as return type in your factory method.

As an alternative, more generic approach, you could let your class conform to a factory protocol which contains a default implementation for the factory method. With this, the static factory method isn't tied to any specific class, but can however be accessed by any class conforming to the factory protocol (and an additional help protocol for common initializers).

Factory setup:

protocol FactoryInitializers {
    var commonProperty : Int { get set }
    init(commonProperty: Int)
}

protocol FactoryMethods {
    typealias T: FactoryInitializers
    static var defaultStaticCommonProperty : Int { get }
}
extension FactoryMethods {
    static func getInstance() -> T {
        return T(commonProperty: defaultStaticCommonProperty)
    }
    static func getInstanceFor(commonProperty commonProperty: Int) -> T {
        return T(commonProperty: commonProperty)
    }
}

protocol Factory : FactoryMethods, FactoryInitializers { }

Example class conformances:

class MyClass : Factory {
    typealias T = MyClass
    static var defaultStaticCommonProperty : Int = 1

    var commonProperty : Int = 0

    required init(commonProperty: Int) {
        self.commonProperty = commonProperty
    }
}

class MyOtherClass : Factory {
    typealias T = MyOtherClass
    static var defaultStaticCommonProperty : Int = 10

    var commonProperty : Int = 0

    required init(commonProperty: Int) {
        self.commonProperty = commonProperty
    }
}

Example usage:

var foo = MyClass.getInstance()
print(foo.dynamicType)    // "MyClass"
print(foo.commonProperty) // 1
foo = MyClass.getInstanceFor(commonProperty: 5)
print(foo.commonProperty) // 5

var bar = MyOtherClass.getInstance()
print(bar.dynamicType)    // "MyOtherClass"
print(bar.commonProperty) // 10

Upvotes: 0

RobbeR
RobbeR

Reputation: 485

self works in static methods too, like this:

class MyClass {
  static func prepare(){
    print("Hello");
  }

  static func doIt() {
    self.prepare();
  }
}

Upvotes: 4

Related Questions