Extensions-visible "private" Access Level


(Uros Krkic) #1

*Introduction*
In order to follow Single Responsibility Principle, I break my types (but
let's talk about classes) into smaller pieces, decouple it and try to give
every single piece a separate functionality.

*Motivation*
Extensions, as a mechanism to extend an existing type, improve this kind of
decoupling and make it possible to keep an extension in a separate compile
unit (file).

*Additional observation is that I personally don't see any purpose or value
of an extension put in the same file as the type it extends. Ultimately, we
will finish with a large class, with a lot lines of code, as if we put
extensions' implementation directly in the type.*

So, let's consider the cases when we want to put extensions in a separate
file (separated of the original type file).

But here, I find the problem to access private members of my original type.
If I define it to be "private" (which is my intention), unfortunately, I
cannot access these members in the extension, but I need them.

Also, I see it very regular and useful to access original type members in
an extension. As the name implies, we extend it. Why not to have full
access to original type? We cannot break any logic or violet something.

*Example*
Let's consider an example where we have UsersViewController which has a
stored property "users" (let' say it is our model) and we want to keep it
private. Let's suppose that UsersViewController uses UITableView and it
handles datasource/delegate implementation. But, let's move
datasource/delegate protocols implementation in an extension in a separate
file named UsersViewController+TableView (Obj-C category naming style).
This extension cannot access "users" property, because it is private.
There are many other examples where we can apply the same approach.

*Solutions*
- Add another access level modifier (but it would be too much to have only
one for extensions):
For example *extensionprivate var users = [User]()*
This looks bad and complicates general understanding of access levels
modifiers.

- Keep the existing access levels to work as-is, but allow marking original
type with something like *@extension-internal*. *This will just allow
"private" access level to be visible inside any extension of the type.* (*I
personally like this approach*, because all Swift access level modifiers
will work as it is designed, but if a developer mark the original type with
@extension-internal, it will just make private modifier visible inside the
extension, but it is clearly stated it was the developer's intention).

- Modify "private" access level to be visible in an extension. I suppose it
is now not possible, because it will break your private vs fileprivate
functionally.

*Benefits*
We (developers) can follow SRP, keep our classes smaller, keep our files
smaller, without mixing different levels of abstraction, keep class (file)
cohesion very high. Accessing private members of original type does not
break SRP or violate a good design, especially in most cases when we are
talking of an extension, we are talking about behavior extension (functions
or protocol implementations). We will continue to encapsulate our
functionalities in well defined types, keeping private all the things we
don't want to share with outside world, but allowing it to be used directly
in our type extensions.

Best regards,

ยทยทยท

--
Uros Krkic