This question has the same form as the copy, and the same solution. Make the mutation an initializer, not a method.
protocol Copyable { init(copy: Self) } protocol Mutatable : Copyable { init(byMutating: Self) } class C : Mutatable { var a = 0 required init(_ a: Int) { self.a = a } required init(copy: C) { a = copy.a } required convenience init(byMutating: C) { self.init(copy: byMutating) self.a++ } }
But to repeat Matt's point in a related article, you can have the C(copy: x) syntax pretty handy, and you can have the copy(x) syntax pretty handy, and there is always x.dynamicType(copy: x) . But you cannot have x.copy() syntax without any annoying work. You need to either duplicate func copy() -> Self { return copy(self) } in each class, or you need to create some specific class that implements this method, and C will ultimately inherit. This is currently the main limitation of Swift. I agree with Matt in diagnosing possible solutions and suspect that in the future some kind of trait system will probably be added, possibly according to Scala.
Itโs worth paying attention to Mattโs comment that โall this underlines the significant tension between methods and functions in Swiftโ. This is another way of saying that there is tension between the object-oriented paradigm and the functional paradigm, and moving between them can lead to some outages. Languages โโtry to solve this problem with various functions, but there are important differences between objects with messages and properties, vs functions with data and combinators, and "getting the best of both worlds" can sometimes create some rough edges.
It's easy to forget that when comparing Swift with other languages, there is a big difference between v0.9 and v2.11. Many things that we take for granted in our favorite languages โโalso did not exist in their v1.
In your comment, you might think that mutated is of type Self . But this is type C , as your autocomplete indicates. As before, C does not match Self if you cannot promise that there are no subclasses ( C as final or struct). Swift types are allowed at compile time, and not at run time, unless you use dynamicType .
To be more specific, Swift looks at this line:
let mutated = copy(self)
He notes that copy is common to the type of its parameter, and he must build a copy version at compile time for the call. No type of Self . It is just a placeholder and should be allowed at compile time. Type Self in this lexical domain C Therefore, it builds copy<C> . But if you subclass C , it may be the wrong function (and in this case it will). This is very closely related to: https://stackoverflow.com/a/3122/2/
The fact that the autocomplete type says (C) , not C , is a secondary side effect of Swift functions and tuples, and quite often appears, but I have yet to meet a case where it really matters, a Swift function such as func f(x: Int, y:Int) , in fact, does not have two parameters. It has one parameter from 2 elements of type (Int, Int) . This fact is important for how the currying syntax works (see Swift for more information on currying in Swift). Therefore, when you specialize in copy , you specialize in it with a 1-tuple of type (C) . (Or perhaps the compiler is simply trying to do this as one of various attempts, and this is only the one it reports to.) In Swift, any value can be trivially replaced with one tuple of the same type. So the copy return is actually a 1-tuple of C written by (C) . I suspect that the Swift compiler will improve its messages over time to remove extraneous parentheses, but sometimes they appear.