Whatever we do, we need to source/binary compatibility to consider now.
Could we say that a protocol’s requirements can optionally be defined with the protocol’s name as a prefix if you don’t just want to use your property/func/etc with the same name?
protocol A {
var foo: Int {get}
}
protocol B {
var foo: Int {get}
}
struct C {
var foo: Int
var bar: Int
}
To conform C
to A
and B
, you could write the same thing you’d write now:
extension C: A, B {}
or you could do something different if you and the author of A
disagree on the semantics of foo
extension C: A, B {
var A.foo: Int { bar }
// no need to specify `B.foo`
}
You could also specify them directly in the type of you want the protocol’s properties to have different storage than your own properties of the same name:
struct D: A, B {
var foo: Int // same as `A.foo`
var B.foo: Int // different storage from `self.foo`
}
In generic code, you’d get the version associated with the protocol constraints:
func baz<T: A>(_ v: T) -> Int {
v.foo // returns `v.A.foo`
}
func buz<T: B>(_ v: T) -> Int {
v.foo // returns `v.B.foo`
}
It’d need some disambiguation in generic code in which the type is constrained to both protocols:
func faz<T: A&B>(_ v: T) -> Int {
v.foo // does it return `v.A.foo‘ or `v.B.foo`?
}
I would say that if there isn’t a “custom” implementation for either protocol conformance, then the compiler knows that both v.A.foo‘ and
v.B.foo` are the same thing and it doesn’t matter. As soon as one of the protocol conformances gets “customized”, the compiler can’t know which one you mean and you’d have to specify:
func faz<T: A&B>(_ v: T) -> Int {
v.A.foo + v.B.foo // `v.foo` would be an error.
}
In generic code where the type is constrained to be a subclass of a class which contains a property with the same name as a protocol property and it has a “custom” conformance, the non-prefixed property refers to the original storage:
class E: A {
var foo: Int
var A.foo: Int { foo - 10 }
}
func fez<T: E>(_ v: T) -> (Int, Int) {
(v.A.foo, v.foo)
}
let e = E(foo: 20)
fez(e) // returns (10, 20)
Dunno, it’s oh wow, 2:45am here. Apologies if I missed something obvious. I might prefer @Joe_Groff‘s @implements(A.foo) var foobaz: Int
syntax... not sure... it’s longer, but it’s maybe clearer. Plus it seems like having it be an attribute might maybe align with some hypothetical future code generation or macro system where maybe you want to, um, log something every time you call a function that’s the same name as a protocol requirement but isn’t the same implementation? I’m not sure why you’d want to do that, but whatever, it’s 2:52am now and my think has stopped braining.