[swift-evolution] [Pitch] Tweak `Self` and introduce `Current`
Xiaodi Wu
xiaodi.wu at gmail.com
Sat Jan 7 16:53:41 CST 2017
On Sat, Jan 7, 2017 at 4:00 PM, Braeden Profile via swift-evolution <
swift-evolution at 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 at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170107/495421f8/attachment.html>
More information about the swift-evolution
mailing list