> 
>  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

Reply via email to