1

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
}
A T
  • 13,008
  • 21
  • 97
  • 158

2 Answers2

1

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.

Steve
  • 921
  • 1
  • 7
  • 18
  • This is absolutely the preferred solution. Generics would be the wrong tool here, and mixing protocols (i.e. `Self`) with class inheritance is Pandora's box in Swift. There is no reason to create complexity to try to avoid one clear line of code. – Rob Napier Feb 25 '18 at 16:20
  • but the superclass Singleton should contain a private init, so that's not possible, right? – swalkner Jan 25 '21 at 20:08
1

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.

A T
  • 13,008
  • 21
  • 97
  • 158
  • I’m not sure I follow what this solution is providing you that static lets in each subclass wouldn’t be doing with less code? Can you explain I’m curious but also glad you found a solution. – Steve Mar 04 '18 at 01:05
  • The thing is, I want to contract `class`es to conform to an interface; one which requires it to implement the Singleton pattern. `static let`s wouldn't let the instance be redefined. The instance needs to be re-definable because the `.root` value is taken at runtime (from `UserDefaults`), and can be changed so I need to recreate all the objects. Also using the `static let`s like you answered, won't conform to any interface. – A T Mar 04 '18 at 01:22