[swift-evolution] [Pitch] Tweak `Self` and introduce `Current`
Braeden Profile
jhaezhyr12 at gmail.com
Sat Jan 7 16:00:15 CST 2017
>
> 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."
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170107/18af8048/attachment.html>
More information about the swift-evolution
mailing list