Custom class clusters in Swift

前端 未结 7 1924
灰色年华
灰色年华 2020-12-02 00:04

This is a relatively common design pattern:

https://stackoverflow.com/a/17015041/743957

It allows you to return a subclass from your init calls.

相关标签:
7条回答
  • 2020-12-02 00:32

    We can take advantage of a compiler quirk - self is allowed to be assigned in protocol extensions - https://forums.swift.org/t/assigning-to-self-in-protocol-extensions/4942.

    Thus, we can have in place something like this:

    /// The sole purpose of this protocol is to allow reassigning `self`
    fileprivate protocol ClusterClassProtocol { }
    
    extension ClusterClassProtocol {
        init(reassigningSelfTo other: Self) {
            self = other
        }
    }
    
    /// This is the base class, the one that gets circulated in the public space
    class ClusterClass: ClusterClassProtocol {
        
        convenience init(_ intVal: Int) {
            self.init(reassigningSelfTo: IntChild(intVal))
        }
        
        convenience init(_ stringVal: String) {
            self.init(reassigningSelfTo: StringChild(stringVal))
        }
    }
    
    /// Some private subclass part of the same cluster
    fileprivate class IntChild: ClusterClass {
        init(_ intVal: Int) { }
    }
    
    /// Another private subclass, part of the same cluster
    fileprivate class StringChild: ClusterClass {
        init(_ stringVal: String) { }
    }
    

    Now, let's give this a try:

    print(ClusterClass(10))    // IntChild
    print(ClusterClass("abc")) // StringChild
    

    This works the same as in Objective-C, where some classes (e.g. NSString, NSArray, NSDictionary) return different subclasses based on the values given at initialization time.

    0 讨论(0)
提交回复
热议问题