[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