Swift inheritance of singleton pattern?

1.8k Views Asked by At

Have this class which is never used directly, only inherited:

class ApiBase {}

How do I define a generic static singleton default here? - So I can:

class FooApi: ApiBase {}  // Want only one instance of `FooApi`
class BarApi: ApiBase {}  // Want only one instance of `BarApi`

FooApi.default.foo_api_only_method_name()
BarApi.default.bar_api_only_method_name()

The only thing I can think of is to create a protocol which FooApi and BarApi need to implement. But that seems suboptimal, would prefer to write an implementation like:

func `default`<T: ApiBase>() -> T {
    if staticInstance == nil {
        staticInstance = T()
    }
    return staticInstance
}
2

There are 2 best solutions below

2
A T On BEST ANSWER

Ended up adding an interface:

protocol Instance {
    associatedtype T
    // static var _instance: T {get set}  # Can't use; can't override :(
    static func instance() -> T
}

Usable like so:

class ApiBase: Instance {
    var root: String = ""

    static var _instance: ApiBase = ApiBase()

    open class func instance() -> ApiBase {
        if _instance.root == "" {
            _instance = ApiBase()
        }
        return _instance
    }
}

Inheritance:

class FooApi: ApiBase {
    static var _fooApi: FooApi = FooApi()

    override class func instance() -> FooApi {
        if _fooApi.root == "" {
            _fooApi = FooApi()
        }
        return _instance
    }
}

This is suboptimal, as the body's of the instance functions are identical in pattern. But it works.

2
Steve On

I was unable to find a way to solve this using generics but my suggestion would be to put

static let `default` = FooApi()

and

static let `default` = BarApi()

into the two subclasses. That way each would create its own singleton without too much additional code.