access modifiers in protocols
access modifiers in protocols
- Subject: access modifiers in protocols
- From: Roland King <email@hidden>
- Date: Wed, 17 Jun 2015 12:58:53 +0800
Is there a good linguistic reason why access modifiers which restrict access should not be allowed in protocols? I mean something like this
public protocol Foo
{
mutating func foo( Int )->Void
internal var bar : Array<Int> { get set } // <- can’t do this
}
What do I think this would mean? I mean by it that a Type conforming to Foo must be public, and must have a public function foo and an internal variable bar.
Why would I want to do this? What I was trying to do is use protocol extensions to provide a default implementation of a protocol method, one which requires a backing property. So the code I really wanted to write was this
public protocol Foo
{
mutating func foo( Int ) -> Void
}
That’s my public definition of the Foo protocol, I don’t care how it’s implemented. Let’s say however that a very usual implementation of foo() would use an Array<Int> property like this
public struct FooImpl : Foo
{
internal var bar = Array<Int>()
public mutating func foo( i : Int ) -> Void { bar.append( i ) }
}
But I have lots of Types which want to implement Foo and although I don’t want to have to copy the method body of foo() everywhere, it might be a little longer in real life. or perhaps Foo has 10 different methods
I could use my FooImpl in all those Types by composition, but then for each method in Foo I have to explicitly call the implementer version. If there’s many methods, that’s repeated code in every Type.
public struct AnotherFooImpl : Foo
{
internal var fooImplementer = FooImpl()
public mutating func foo( i : Int ) -> Void { fooImplementer.foo( i ) ) // do this for each method in Foo
}
What I’d like is for the compiler to do this for me with a protocol extension, I can do this like so by extending Foo like this and using an extension
public protocol FooImplementedWithArray : Foo
{
var bar : Array<Int> { get set }
}
extension FooImplementedWithArray
{
public mutating func foo( i : Int ) -> Void { bar.append( i ) }
}
and then the implementation just requires defining the stored property
public struct AThirdFooImpl : FooImplementedWithArray
{
public var bar = Array<Int>() // that’s all we need = the protocol extension supplies the rest
}
But the problem is .. bar is now public. Worse, as the foo() was cunningly declared to be mutating, bar has to be a { get set } property, anyone using the class can totally break it.
If I make FooImplementedWithArray internal, bar is internal, however that also makes foo() internal and means none of my implementations can be anything more than internal. My feeling was that if you were allowed to mark things in a protocol as more restricted than the protocol itself, eg make bar private within a public FooImplementedWithArray, that would work and the compiler could synthesise the code you would write yourself.
Is there a reason why all protocol elements must have the same visibility as the protocol itself otherwise there’s a potential visibility inconsistency, or is this just a feature I should request.
Is there another way to do what I’m trying to do here, have the compiler do my work for me but have my stored property hidden?
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden