On Sat, Jan 7, 2017 at 4:00 PM, Braeden Profile via swift-evolution < swift-evolution@swift.org> wrote:
> * 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. > That was poor writing on my part. What I meant was that, exactly as you show below, `Building.copy()` needs to invoke a method on a subclass to obtain an instance of type `Self`. There is nothing that `Building` can do without relying on its subclasses in order to obtain such an instance (I can't imagine a use case _why_ one couldn't do that, but I understood Adrian as saying that he has that problem). 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. > Agree, it's a shame that one needs to jump through that hoop with `unsafeBitCast`. With SE-0068, I'd hope that `super.copy() as! Self` would be sufficient. > 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." > > Agree. That seems wrong. Great example. _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution