> here is the scenario, I want to implement a Copying protocol which can be
> used homogeneously
>
> protocol Copying {
> func copy() -> Self
> }
>
> Because this protocol contains neither associated-type-requirements or
> self-requirements(requiring a method returning Self is different), it can
> surely be used homogeneously.
>
> let objects: [Copying] = ....
> for copyable in objects {
> .....
> }
But Copying does contain a Self requirement. It is used the result of the
copy() method
Here is how I implement Copying :
protocol Copyable
{
func copy() -> Self
init(other: Self)
}
// This extension provides a default implementation
extension Copyable
{
func copy() -> Self
{
return type(of: self).init(other: self)
}
}
implementing Copyable on a struct is simple :
struct Struct : Copyable
{
var value: String
init(value: String)
{
self.value = value
}
init(other: Struct)
{
value = other.value
}
}
But implementing it on a class is slightly more troublesome.
class Shape : Copyable
{
var color: NSColor
init(color: NSColor)
{
self.color = color
}
}
At this stage, the compiler (obviously) screams that Copyable is not
implemented but the first "error" it notices it marks as being on the default
implementation in the extension: Method 'copy()' in non-final class 'Shape'
must return `Self` to conform to protocol 'Copyable'
Marking this error on the extension method, which obviously does exactly what
the error says is missing ???
Implementing the copy() method in Shape kills this error message but leaves me
wondering why I have to now repeat the exact same code in the implementing
method that I wrote in the default method in the protocol extension ; something
that the compiler is completely ignoring.
Implementing the protocol with a struct takes account of the default method but
with a class ignores it. This smells remarkably like a bug !
Nonetheless, I now end up with the following code, complete with duplicate
copy() method :
class Shape : Copyable
{
var color: NSColor
func copy() -> Self
{
return type(of: self).init(other: self)
}
init(color: NSColor)
{
self.color = color
}
required init(other: Shape)
{
color = other.color
}
}
Then I can go on to declare subclasses :
class Circle : Shape
{
var radius: Double = 0.0
init(color: NSColor, radius: Double)
{
super.init(color: color)
self.radius = radius
}
required init(other: Shape)
{
super.init(other: other)
if let other = other as? Circle
{
radius = other.radius
}
}
}
class Square : Shape
{
var side: Double = 0.0
init(color: NSColor, side: Double)
{
super.init(color: color)
self.side = side
}
required init(other: Shape)
{
super.init(other: other)
if let other = other as? Square
{
side = other.side
}
}
}
And, the, if I create an extension to Array :
extension Array where Element : Copyable
{
func copy() -> Array<Element>
{
var result = [Element]()
self.forEach { result.append($0.copy()) }
return result
}
}
I can then use the following code to create an array of Shapes but, obviously
not of Copyable, due to its restrictions on the Self requirements on the
protocol.
{
let shapes = [Circle(color: .black, radius: 5.0), Square(color: .black, side:
5.0)]
let copies = shapes.copy()
…
}
Thus, another possible solution to your problem is to declare the required
init(other: Self) in the protocol.
Which still leaves my question of why I have to reimplement the default
copy(other:) method from the protocol's extension in the base class ???
Joanna
--
Joanna Carter
Carter Consulting
_______________________________________________
swift-users mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-users