> > One could workaround the problem and use final, but what if the class > meant to be subtypeable? Self simply does not work in this scenario. > > > It works exactly as it should in this scenario. If A isn't final, then by > definition it's impossible for A to make a copy of type Self. I see, > however, what you mean, which is that you wish you could write a protocol > requirement for a function that returns #Self.
What do you mean? Even with the limited `Self` support in Swift 3, I can write a very effective copying paradigm. protocol Copyable { func copy() -> Self } class Building: Copyable { var floors = 1 required init() { } func copy() -> Self { let dynamicType = type(of: self) let newObject = dynamicType.init() newObject.floors = self.floors return newObject } } class Mansion: Building { var butlers = 3 override func copy() -> Self { // let newObject = super.copy() let newObject = super.copy() as! Mansion newObject.butlers = self.butlers // return newObject return unsafeBitCast(newObject, to: type(of: self)) } } let hoboHouse = Building() hoboHouse.floors = 0 let beggarHouse = hoboHouse.copy() print(beggarHouse.floors) // "0" let myHouse = Mansion() myHouse.floors = 4 let yourHouse = myHouse.copy() print(yourHouse.floors) // “4” Besides the poor support for `Self` in the function body (SE–0068 fixes that), it seems like an acceptable way of doing it. Of course, I would love being able to use an initializer setup, but there are serious bugs in the implementation. protocol Clonable { init(other: Self) } extension Clonable { func clone() -> Self { return type(of: self).init(other: self) } } class Base: Clonable { var x: Int init(x: Int) { self.x = x } required init(other: Base) { self.x = other.x } } class Derived: Base { var y: String init(x: Int, y: String) { self.y = y super.init(x: x) } // Should be required by the Clonable protocol, but it isn't. required init(other: Derived) { self.y = other.y super.init(other: other) } // Required because it was `required` in Base. Even a `Derived` calls this initializer to clone, which is wrong. Bugs abound. required init(other: Base) { fatalError("init(other:) is wrong.") } } let me = Derived(x: 1, y: "food") let alienClone = me.clone() // "init(other:) is wrong."
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution