Search code examples
swiftinheritancestatic-methodsfactory-method

Inheritable static factory method in Swift class


Consider this static factory method written in Objective-C:

@implementation User

+ (instancetype)named:(NSString *)name {
    let user = [self new];
    user.name = name;
    return user;
}

@end

How do I implement it in Swift? The plenty of Self/self/Type/type keywords in Swift feels fuzzy and I struggle to figure out the right solution.


Solution

  • The solution came out to be like this:

    class User {
        var name: String
    
        required init(name: String) { self.name = name }
    
        class func named(_ name: String) -> Self {
            let instance = Self.init(name: name)
            return instance
        }
    }
    

    The following example shows everything works fine:

    class Admin: User {
        override class func named(_ name: String) -> Self {
            let decoratedName = "~\(name)~"
            let instance = Self.init(name: decoratedName)
            return instance
        }
    
        func ban(user: User) {
            print("User \(user.name) banned by \(name)!")
        }
    }
    
    let user = User.named("John")
    let admin = Admin.named("Peter")
    admin.ban(user: user) // Yields 'User John banned by ~Peter~!'
    

    So, you should pay attention to these keypoints:

    • Your class must have a required constructor (maybe even without arguments)
    • You should call it on Self. inside your method
    • Your method should have class access modifier
    • Your method's return type should be -> Self (note the capital S)