Protocol func returning Self

后端 未结 9 1813
悲哀的现实
悲哀的现实 2020-11-22 15:11

I have a protocol P that returns a copy of the object:

protocol P {
    func copy() -> Self
}

and a class C that implements P:



        
相关标签:
9条回答
  • 2020-11-22 15:59

    With Swift 2, we can use protocol extensions for this.

    protocol Copyable {
        init(copy:Self)
    }
    
    extension Copyable {
        func copy() -> Self {
            return Self.init(copy: self)
        }
    }
    
    0 讨论(0)
  • 2020-11-22 16:01

    Following on Rob's suggestion, this could be made more generic with associated types. I've changed the example a bit to demonstrate the benefits of the approach.

    protocol Copyable: NSCopying {
        associatedtype Prototype
        init(copy: Prototype)
        init(deepCopy: Prototype)
    }
    class C : Copyable {
        typealias Prototype = C // <-- requires adding this line to classes
        required init(copy: Prototype) {
            // Perform your copying here.
        }
        required init(deepCopy: Prototype) {
            // Perform your deep copying here.
        }
        @objc func copyWithZone(zone: NSZone) -> AnyObject {
            return Prototype(copy: self)
        }
    }
    
    0 讨论(0)
  • 2020-11-22 16:04

    To add to the answers with the associatedtype way, I suggest to move the creating of the instance to a default implementation of the protocol extension. In that way the conforming classes won't have to implement it, thus sparing us from code duplication:

    protocol Initializable {
        init()
    }
    
    protocol Creatable: Initializable {
        associatedtype Object: Initializable = Self
        static func newInstance() -> Object
    }
    
    extension Creatable {
        static func newInstance() -> Object {
            return Object()
        }
    }
    
    class MyClass: Creatable {
        required init() {}
    }
    
    class MyOtherClass: Creatable {
        required init() {}
    }
    
    // Any class (struct, etc.) conforming to Creatable
    // can create new instances without having to implement newInstance() 
    let instance1 = MyClass.newInstance()
    let instance2 = MyOtherClass.newInstance()
    
    0 讨论(0)
提交回复
热议问题