On 15.02.2017 14:29, Joanna Carter via swift-evolution wrote:
The beauty of Swift 2's access modifiers was that they were based
around files and modules, explicitly rejecting types and scopes as
units for determining visibility. It seems at base there's a group of
people who reject that decision altogether. Hence, new `private`,
proposals around `protected`, `friend`, `hidden`, `extensible`, etc.

I suppose, for those coming from an Objective-C only background, any
extra visibilities are seen as a bonus.

For those coming from a Pascal background, file-based visibility seems
more natural.

But for those of us who have used languages like C++ and C#, losing the
visibilities that we have been used to can seriously affect how we think
and design stuff.


Was surprised that you expressed exactly what I'm thinking about this subject.

I do believe even in Swift we need a way to say "only code that *knows* what it does should see this" and to not force us to write(and manage) the the code in same file. Yes, some implementation details that shouldn't be used by "users" of the type, but can be used by "extenders" of our type. At least in the same module.

While reading, the question was raised(if was discussed, let me know pls): what if we extend the meaning of 'private' to 'visible to current type/scope and subtypes and extensions in the *same module*' ? This will help us to split types by files, help to better model access policy for fields/methods(i.e. only scope that can know about details can see them) while 'private' still will be hidden outside of the module even for subclasses/extensions.

So, we'll have such situation:

"modifier" -> "can be accessed from"
-------------------------------
public -> outside of the mondule
internal -> inside the module only
fileprivate -> the same file only
private -> the same type/scope, or subtype, or extension in the same module. I.e. some kind of 'internal' but scope-oriented.

Actually I still believe we need current 'private' and additionally some 'protected' with meaning "access from subtype, or extension" probably with this limitation: "only in the same module". But suggested extended 'private' will be also OK for me.

Thoughts?

Vladimir.

FMPOV, it would seem that one of the "features" of Swift is a much more
protocol and struct approach to design. Instead of using class
inheritance to add functionality to an entity, we are encouraged to use
extensions.

But, in so doing, those of us who are used to inheritance find that we
can no longer limit visibility to a "hierarchy" but, instead, when we
want to extend a type whilst accessing "privileged" members, we either
have to put all our extensions in the same file as the base type, or
raise the visibility of those privileged members to internal scope, thus
allowing code anywhere in the same module to access and/or mutate it.

I have read https://developer.apple.com/swift/blog/?id=11 and I can see
the reasoning against protected explained there but…

Once again, I see the "it was good enough for Objective-C" reasoning
being a strong driver here but, this is Swift, where things can be done
differently/better.

Allowing internal scope visibility is less of a problem when you are the
only one writing the module and know intimately the intent and purpose
of everything but when working in a team environment, it is all too easy
for another developer to start "interfering" with your carefully
designed logic by using it in ways that you had not anticipated.

I can understand the reasoning behind not using the concept of protected
visibility but still feel that there are times when restricting
visibility only to extending entities, whether that be subclasses of a
class or extensions of any type, including structs and enums.


I would also like to argue that the use of open vs public for classes is
quite confusing when we already have the option of marking a class or
its members as final ; which seems to do much the same as leaving a
class as public.

Except open is not truly a restriction of visibility, it is more a
restriction on inheritance.

To quote the above blog, "In contrast, protected conflates access with
inheritance". Surely "open" also conflates access with inheritance? It
affects, not what external code can see but how the inheritance chain is
controlled, as does final. In fact, I would dare to say that the
difference between open/public and final is possibly too fine to be of
sufficient importance to justify the existence of both ; or, at least,
it is sufficiently confusing to encourage newer developers to throw
their hands up in despair and simply leave everything as internal or
public until they stumble across a compilation error.

The only real difference I can make out between open/public and final is
that, once again, open/public is more module-based, whereas final is
class based.

Why, when we are allowed final as a class only modifier, can't we have
protected as a class only visibility?

Or, as I have mentioned previously, should we have a much more "Swifty"
version of protected that allows more concisely defined visibility, not
only within class hierarchies, but also within the full range of Swift
"hierarchies", otherwise known as extensions?

My suggestion of "extensible" is intended to replace the perceived need
for "protected" for classes, whilst unifying that concept of privileged
access within a class hierarchy, with a similar, and increasingly
demanded, privileged access for extensions of all types.

To elucidate further :

Before Swift, if we wanted a hierarchy of types, all with common base
behaviour, without having to write the same code in every type, we were
limited to using classes with their visibilities of private, protected
and public.

Now Swift encourages us to declare protocols, which can have extensions
that can define base behaviour, as long as that behaviour doesn't
include stored data. We can then "inherit" that behaviour either in
classes, structs or enums that implement the "base" protocol.

So, an interesting question is : should we look at getting rid of class
inheritance altogether in favour of "protocol-based inheritance"?


Oh, and finally for this post, can anyone please tell me exactly what
fileprivate brings to the table?

To my mind, although it allows access to private members of another
type, it also requires that any type, wishing to take advantage of that
privilege, has to be declared in the same file ; so, sort of like
protected visibility but on a file basis.

But what if I have a relatively small abstract type (protocol or class)
that is the basis of a larger "hierarchy"? Using fileprivate in the base
type would mean that I would have to declare my whole hierarchy within
that one file instead of placing each "subtype" or "implementing type"
in their own files.

What happened to the "types should only be one screenful" school of
thinking? :-)

-- Joanna Carter Carter Consulting

_______________________________________________ swift-evolution mailing
list swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to