Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Access Control in Swift (developer.apple.com)
81 points by rjsamson on July 24, 2014 | hide | past | favorite | 44 comments


Note that as seems to be in vogue these days (Go, Rust), access to a class's methods and fields is never directly tied to code being "inside" the class; even `private` entities are accessible from anywhere in the same source file. I guess this is a good thing, as it avoids awkwardness with anything implemented as a function rather than a method, and works as a substitute for most cases where "friend" would be acceptable coding style in C++.


You can say it's "in vogue" these days, but C had private, public, and internal visibility (private = declared in .c file, public = declared in public .h file, internal = declared in private .h file). It's not just that you can technically accomplish this in C, but people actually use this all the time. Look at almost any library and you'll find this. Other languages have had module and library scopes for accessibility for decades as well. It's really an aberration that some languages make it so that data structures are the scope for symbol accessibility. C++'s accessibility rules are just bizarre and awkward for polyglots.


I wrote about how it is like C [0] the other day. I should update the post with links to the Apple blog and some of things said on the forum. Maybe tonight.

[0] http://blog.human-friendly.com/swift-access-controls-are-lik...


Yes, C++ gave tools and then "language lawyers" started to introduce practically dubious rules where every class has to carefully guard its own variables.

In the saner practice, however, you want to develop subsystems where the classes that are the part of the subsystem cooperate to the common goal, not protect themselves from their peers (some "OO" C++ language lawyers are certainly already offended by my claim). Even if some class is in charge for something, it's easier when more classes can at least see some pieces of the data without making a lot of getters and setters "just because."


In Go at least, you can certainly enforce private fields and methods on a strict to be accessible only within the scope of the package.


There's also a blog post preceding this one that talks about call-by-name-esque semantics using "@auto_closure"; it's definitely worth a look.


Anybody else missing "protected" access? Looking at the semantics of "private" I doubt it's coming...


I think one of the problems with protected is it over emphasises inheritance over composition. Swift isn't only a object based language but a functional one too with functions/blocks/closures playing a big role and potentially needing just as close access to the objects they act on as subclasses might.


Can someone please explain to me under what situations "protected" is not just a variant of "public"? Any time you can inherit from the class, if you want access to its members you simply create a new subclass and access anything protected. If you can't inherit from the class (because it's package-private, for example) protected members serve no clear purpose. I've always felt that a language could get away with just package-private and public, so it's been nice to see so many modern languages embracing that.


Ok, let's say you have a class that performs some process - ProcessBase. It then needs to call Step1(), Step2(), and Step3() methods. I had a similar case a few months ago at work.

However in certain cases, you need to change what Step2() is, but not break up the process. You don't want outside callers to access Step2() directly, but you need a way to allow a subclass to define it's own Step2() while keeping the overall process intact.

So you would make those three methods protected (and, depending on language, virtual) and override as needed in a subclass.

That's the use case I've used protected for.

Also, I may want to do things internally inside my package/module/library that I want to be able to internally override, but not make it part of my API in case I want to change it later.


Here's what I don't understand: either you need to modify it within its own package (so you can use package-private to prevent anyone else from accessing it) or you have to leave it available for potentially anyone to modify, as you already are when you make it protected (hence: public). To be clear, I understand why people want protected. I'm just not sure it's strictly necessary from a permissions / invariants standpoint.

(Conversely, your scenario can be precisely solved without violating encapsulation by passing in step2 as a function, and passing in any information it requires as parameters. I suspect most of the usecases for protected go away with first-class functions).


The default "internal" access mode is similar to "protected". It's less granular, but that's to be expected since Swift does not (yet?) allow partitioning of a single app or library into different namespaces.


"internal" offers access to all in the module, not just subclasses.

"protected" would allow you to modify a member of a class when you inherit from it, whether it is in the same module or not.

using "internal" or "public" with a comment saying "please only use this when you subclass" the class is not as neat and tidy.


internel looks more like the default package scope in Java


Ah, shoot, you're right. That's what I was thinking about. It's been a long while since I actively used Java.


It's an interesting choice, but I think I'd have rather had a sensible default for each type category than one (internal) for everything. For instances: public classes, public enums, private or internal ivars, public methods, etc. Just to cut down on the boilerplate.


It seems that they have chosen a default (internal, though I don't know how to interpret how "most of the time" works) which is similar to the default modifier in Java. It seems, though, that java's default modifier was maybe ill-chosen, as private and public modifiers seem far more prevalent than no modifier (which means that the default modifier is used) in java code.


It's like "protected" access, in Java's terms. Subclasses can't access the default members in Java. That is why it is so rarely used. It was oddly restrictive, and didn't seem like it made much sense in most cases. I don't find this as a bad decision, in Swift. Since you don't normally want to expose the internals of your classes, this was a good choice.

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscon...


I think you might have gotten it wrong?

I think it (Swift's internal/default) is more like "package-private" in Java.

It looks almost exactly like C#'s internal:

http://msdn.microsoft.com/en-us/library/ms173121.aspx


ChrisLattner talks about the java in this recent post if you have access to the apple dev site.

https://devforums.apple.com/message/1010693#1010693


> It seems, though, that java's default modifier was maybe ill-chosen, as private and public modifiers seem far more prevalent than no modifier

My impression is that people often simply don't know exactly what the default modifier does, whereas they're more confident in the behaviour of public and private.


I think its pretty unfortunate Apple chose the name used by OpenStack's Object Storage (Swift)...


It's also the same name as one of their own CPU cores (the A6 CPU core was called Swift). And another programming language. And a spacecraft. And a bird.


and that OpenStack's Object Storage chose the name used by a great Jabber client (Swift: http://swift.im/)...


Yes, I find that unfortunate too.

But if you're interested in ACLs in OpenStack Swift, http://swift.openstack.org/overview_auth.html is a good place to start.

(all tongue in cheek)


Finally! If they implement multiple inheritance I think I'll have a nerdgasm!


>If they implement multiple inheritance I think I'll have a nerdgasm!

Honest question: Why would you ever want to use multiple inheritance? It seems like an awful design pattern.

I mean, in C++, you basically just end up with a more confusing equivalent to Java interfaces.


Mix-ins. Think Java 8 interfaces, with default implementations (so you can still have a putAll method as part of the interface, but the default handles the looping logic for you).

You can also do a layering-up type thing, where you have a base class that implements particular functionality, and inheriting from particular classes surfaces it or restricts it in particular ways.


Indeed. And once you have interfaces with default implementations, adding state gets you even more power. For example, intrusive reference counting and intrusive data structures generally are very useful applications of multiple inheritance.


I wrote a report about how using Objective-C categories to implement UIViewController feature modules can be really elegant. [1] The same would be true, I imagine, for what would be Swift's multiple inheritance. The following is a quick summary of this report, with thoughts about multiple inheritance.

You may find yourself having a set of UIViewControllers that implement overlapping subsets of the features that your app provides (i.e. one controller has features A and B, another has features B and C, a third has features C and A).

One method of solving this is to create helper modules that implement the features A, B, and C. In your controllers, you can then set up the appropriate subset of helper modules. There are a few problems with this: 1) there's still boilerplate code; 2) the implementation can be subtle (make sure to retain the reference to all your helper classes!).

This can be elegantly solved with Objective-C categories (by creating a category for each feature) or, I imagine, what multiple inheritance would look like in Swift. Instead of boilerplate helper module initialization and subtle implementation, your ABUIViewController could inherit from abstract AUIViewController and BUIViewController base classes to get both features for free in virtual methods.

[1]: http://srcreigh.github.io/blog/posts/modular-uiviewcontrolle...


Here's the canonical example I used to quote for multiple inheritance: "Implementing the design pattern observer".

You basically want to add public methods addEventListener(), removeEventListener() and a protected fireEvent() method. In Java you have no problem inheriting the interface for these methods. However you want to manually re-implement the damn implementation in each class that vends interface. I can't remember how many times I wrote these...

In C++ with multiple inheritance you can inherit both the interface and implementation, and you're done. It is one step further than Java interfaces.

These days, I don't use that so much and I would not miss multiple inheritance. I prefer to implement the design pattern observer through signals (boost::signal in C++, custom classes in JavaScript/TypeScript). C# delegates provide a good solution for this problem too.

I have not touched Java since 1.4, so maybe there is a more elegant way to solve this now...


You basically want to add public methods addEventListener(), removeEventListener() and a protected fireEvent() method. In Java you have no problem inheriting the interface for these methods. However you want to manually re-implement the damn implementation in each class that vends interface. I can't remember how many times I wrote these...

Why? Just use composition and delegate addEventListener() and removeEventListener() to the member implementing the logic?


That's a good idea. And as that's a common pattern, you could allow the programmer to specify that the compiler should automatically implement this delegation. You could call this feature something like, I don't know, "multiple inheritance".


Then you don't understand composition. I can pass the actual implementation in the constructor or via dependency injection. With multiple inheritance, your class is restricted to one implementation. Moreover, it couples the class with the internals of observables, rather than using simple interfaces, which composition provides.


IMHO multiple inheritance is a bad solution to this problem. I would be more inclined to use a DI pattern and inject an event manager wherever it's needed.

Even when multiple inheritance is genuinely useful, it still feels dirty to me. PHP actually has a nice feature called traits, which is essentially compiler-assisted copy & paste. It means you can re-use code without duplication and without the confusion that multiple inheritance can bring.


Mixins would solve that problem while at the same time avoiding a lot of the issues with multiple inheritance.


Oh dear god, no. People might actually use it.

Better to make protocols fast.


This language feels very unfinished... I've seen 0.8 languages being far more polished. Maybe I'm just biased? Swift looks good though. But it's only as good as the Cocoa framework bindings really.


Version numbers and alpha/beta/delta labels vary and are subjective in practice. I've seen plenty of examples and counter-examples of version numbers and beta labels to not put much merit toward such labels.

Yes, it is unfinished. I'd rather have Apple do what it's doing -- i.e., releasing Swift as a beta and changing things with feedback -- than do the opposite, which would be keeping it closed until it was super polished as they felt it internally.

I hate seeing this "damned if you do, damned if you don't" scenario all the time.

(1) Pre-release for feedback, get complained at for it not being finished.

(2) Polish and release later on, get complained at for not opening it up earlier for public feedback and testing.

Apple has clearly stated that it's pre-release, that it's not set in stone yet, and that they're open to feedback (which they have been).


There's a big difference between someone's pet project language, or even an industry leader's new language in the ether, vs. the next crowned prince of an existing ecosystem.

Despite being backed by Google, regardless of how finished or unfinished Go was upon release, there was no impending pressure that you would someday more or less be forced to rewrite all your existing code in it. Thus the early adopter pros and cons were pretty clear.

This is not the case with Swift. At least if you take Apple at face value, Swift is the future of the ecosystem, which creates kind of a confusing landscape. Whether or not you should be writing your new app in Swift is a hard question. Whether you should just stand in the sidelines and not bother until Swift is more settled is a hard question. Swift is simultaneously in early adopter phase and industry requirement. As such, it is more than a little strange (arguably bordering on irresponsible) to make such a huge announcement when most of your own framework teams had never even seen or tried the language. I don't think there would have been any harm in getting internal feedback from your primary consumers before drawing a line in the sand to the general public.


  Despite being backed by Google, regardless of how 
  finished or unfinished Go was upon release, there 
  was no impending pressure that you would someday 
  more or less be forced to rewrite all your existing
  code in it. Thus the early adopter pros and cons 
  were pretty clear. This is not the case with Swift.
The way I look at this issue, is that for now Swift should only be used for pet projects and the like. Simple projects that help the developer gain experience with the language.


This is somewhat true. However, any developer who's got even the smallest amount of development skills will be able to make the leap from Obj-c to Swift with relative ease. Most of what people end up learning when doing iOS/Mac code are the frameworks, and they're functionally identical (except for syntactic difference of course).


Besides, isn't the challenge of learning new languages what makes being a developer fun? :)


It literally is unfinished!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: