Since swift doesn't use headers to specify it's interface, but access modifiers instead, I wondered if there is a good way to split public and private methods (perhaps in files, extensions or just visually). I'm thinking of the Java-esque way of declaring a FooInterface and FooImpl, but I don't really like the idea. Is there a nicer way to achieve this?
The bottom line is I want to be able to have all public members in one location and the private stuff in another - it just helps to avoid visibility mistakes.
I generally use the technique of declaring a private extension:
private extension MyClass {
}
I do that later in the file. However, that only works for methods. Properties still need to be declared in the main type definition.
You can just declare the methods as private:
private func doSomething() {
}
Related
I'm faced with a situation where I am defining a reusable base class in a module, and I want to provide certain functions that should be callable only by subclasses, not external users of that subclass.
I'm writing a framework and packaging it as a Swift module. Part of my framework includes a base class that can be subclassed to add functionality, but whereby the derived class also has a further external purpose as well. Imagine defining a new kind of view: it derives from UIView or NSView, then provides additional logic, and is then itself instantiated by another party.
In this case, I'm the one defining the UIView-like class that is intended to be subclassed, and along with it comes a lot of private UIView internal stuff, like measurement, arranging, who knows, internal stuff.
The point is, end users of this new view class don't want to see the internals of the architecture that supported the subclassing, those should be completely inside the black box of what the subclass represents.
And it strikes me that this is now impossible in Swift.
I really don't understand why Swift got rid of protected access control. According to Apple, the function that I want to expose only to subclasses "isn't really useful outside the subclass, so protection isn’t critical".
Am I missing something? Is this a whole class of design patterns that Swift simply cannot support?
One thought that occurs to me is I could perhaps split up the public-public and the private-public parts of my class into two parts, perhaps using protocols, whereby public-public users would only see the public protocol and "private" public users would see the "private" protocol as well. Alas this seems like a lot of engineering for something that used to be free.
FWIW — I've been continually asking for better access control in Swift (including protected) since before there was access control in Swift. Now, 3.5 years after we were told to give the Swift approach to access control a try, Swift has been my primary language for almost 3 of those years and I still think the access control paradigm is clumsy and unable to model concepts that are easy in almost all similar languages.
The largest mitigating factor for me is that Swift has steered me away from ever using inheritance and subclassing 95% of the time, which I think is a good thing. So this issue comes up less than it may have otherwise. But for situations exactly as you are describing, there isn't an equivalent way to accomplish what you are doing using only protocols and protocol extensions, so you are stuck either polluting a public API with possibly harmful internal details, or using some workaround (like the one that follows) which has the smallest possible public API exposure, and simulates what you want at the cost of boilerplate and awkwardness.
That said, the approach I take is somewhat inspired by Objective C, where there is also no real protected access control, but the convention is to declare a public API header (which client code will import and reference) and a special "+Subclassing" header which only subclasses will import in their implementation, giving them visibility into the not-for-public-consumption internals.
In Swift, this isn't directly possible either, but given a class like this:
open class SomeClass {
private var foo: String
private var bar: Data
public init(){
foo = "foo"
bar = Data()
}
private func doInternalThing() {
print(foo)
}
}
You can add a nested "Protected" wrapper via extension (has to be in the same file as your class declaration), which takes an instance of the class (or a subclass) and exposes the protected-level internals as a sort of proxy:
// Create a nested "Protected" type, which can accept an instance of SomeClass (or one of its subclasses) and expose the internal / protected members on it
public extension SomeClass {
public class Protected {
unowned private var someClass: SomeClass
public var foo: String {
get {
return someClass.foo
}
set {
someClass.foo = newValue
}
}
public init(_ someClass: SomeClass) {
self.someClass = someClass
}
public func doInternalThing() {
someClass.doInternalThing()
}
}
}
Outside of the framework, in the client application, the protected members are accessed in a subclass like this:
class SomeSubclass: SomeClass {
private lazy var protected: SomeClass.Protected = { SomeClass.Protected(self) }()
func doSomething() {
protected.foo = "newFoo" // Accesses the protected property foo and sets a new value "newFoo"
protected.doInternalThing() // Prints "newFoo" by calling the protected method doInternalThing which prints the foo property.
}
}
There are pros and cons for this approach. The cons are mainly the amount of boilerplate you need to write to map all your properties and functions from the Protected wrapper to the actual class instance as shown above. Also, there is no avoiding the fact that consumers will see SomeClass.Protected as a publicly visible type, but hopefully it's clear that it shouldn't be used and it's difficult enough to use it arbitrarily that it won't happen.
The pros are that there isn't a lot of boilerplate or pain for clients when creating subclasses, and its easy to declare a lazy "protected" var to get the desired API. It's pretty unlikely that non-subclass would stumble upon or use this API accidentally or unwittingly, and it's mostly hidden as desired. Instances of SomeSubclass will not show any extra protected API in code completion or to outside code at all.
I encourage anyone else who thinks access control — or really in this case, API visibility and organization — to be easier than it is in Swift today to let the Swift team know via the Swift forums, Twitter, or bugs.swift.org.
You can kinda, sorta work around it by separating out the for-subclasses stuff into a separate protocol, like this:
class Widget {
protocol SubclassStuff {
func foo()
func bar()
func baz()
}
func makeSubclassStuff() -> SubclassStuff {
// provide some kind of defaults, or throw a fatalError if this is
// an abstract superclass
}
private lazy var subclassStuff: SubclassStuff = {
return self.makeSubclassStuff()
}()
}
Then you can at least group the stuff that's not to be called in one place, to avoid it polluting the public interface any more than absolutely necessary and getting called by accident.
You can also reconsider whether you really need the subclass pattern here, and consider using a protocol instead. Unfortunately, since protocols can't nest types yet, this involves giving the subclass-specific protocol an Objective-C-style prefixed name:
protocol WidgetConcreteTypeStuff {
...
}
protocol Widget {
var concreteTypeStuff: WidgetConcreteTypeStuff { get }
}
I've completed a online course that taught us to write properties of classes as:
class bar {
private var _foo:Int
var foo {
return _foo
}
}
Since then i've seen
class bar {
private (set) var foo:Int
}
Is there any difference between these two ways of writing things, and which would be best practise?
The second option is simpler and clearer and it has the added benefit of still being able to add get, set, willSet, and didSet blocks on the property while still having clearly defined scope on the getter and setter. Of course you can still add those to the private property but I think the code starts to get less readable.
Also note that the first option is a public read-only computed property making use of a private stored property.
The second option can be either a computed or stored property.
I'm using a third-party library for a new app that I'm making using Swift. The author of the class/library has made it final using the final keyword, probably to optimise and to prevent overriding its properties and methods.
Example:
final public class ExampleClass {
// Properties and Methods here
}
Is it possible for me extend the class and add some new properties and methods to it without overriding the defaults?
Like so:
extension ExampleClass {
// New Properties and Methods inside
}
An extension may not contain stored properties but you can add methods inside.
Extensions (like Objective-C categories) don't allow stored properties.
Methods and computed properties are fine though.
A common (but IMO hacky) workaround in Objective-C was to use associated objects to gain storage within categories. This also works in Swift if you import ObjectiveC.
This answer contains some details.
Yes, you can extend a final class.
That extension has to follow the usual rules for extensions, otherwise it's nothing special.
While you cannot create new stored properties in extensions you can add methods and computed properties.
Example computed property:
extension ExampleClass {
// computed properties do not have a setter, only get access
var asInt: Int? {
Int(aStringPropertyOnTheClass)
}
}
Coming from Objective-C, I am very fond of header files which expose the interface of a piece of code. Swift has always bothered me a bit because even the most organized code still tends to bury the public/private API's among the rest of the code, making you dig for details.
Are there any practices or tricks where I can define the public interface of a class or module external to the implementation? Right now I'm just making comments at the top of the Swift file and it feels arcane.
As far as I know you can not just declare a method in a class and implement it at other places in Swift.
I feel you want that for clarity and organizing your methods into class. To achieve that in Swift I follow some techniques that I would be happy to share with you:
Organize methods in groups based on access i.e. public, private and internal. Public methods on top as you want your client to look at them first, then internal and last private.
You may sub organize related methods together for making it easy to understand, maintain and navigate through.
Some time it is good to break above rules to group public and private method if they are related and has heavy dependancies.
You may group related methods that do a specific task in to extensions. I generally follow this pattern for implementing specific protocol or delegate in a class. This you could do in a separate file as well.
This is not direct answer to your question but I have tried to address the core of it by targeting organization of methods in a class.
So I've been exploring the options here and it looks like you can define an interface using a protocol, and having your class conform to that protocol. Kind of out of the way, but if a public interface is the goal, this achieves that.
// Foo.swift
protocol PublicFoo {
func publiclyExposedMethod(arg:AnyObject) -> AnyObject
var publiclyExposedVariable:AnyObject
}
class Foo : PublicFoo {
var publiclyExposedVariable:AnyObject = // something
func publiclyExposedMethod(arg:AnyObject) -> AnyObject {
// do stuff...
}
}
Regarding class public class declaration, please look at these two pieces of code:
public class Helper
{
public static void CallMeganFox(string phoneNumber)
{ //...
and
public static class Helper
{
public static void CallMeganFox(string phoneNumber)
{ //...
What is better to use and why?
It's "better" in theory to make it explicit that this class is not supposed to be instantiated by making it static (second option), because it communicates intent¹.
However in such a simple case, from a practical perspective there will be exactly zero difference². Noone's going to look at this class and try to instantiate it.
¹ As Cody Gray points out, it can also help you catch mistakes earlier (e.g. forgetting to make a helper method static). While that viewpoint certainly has merit, again the practical difference is going to be negligible: the compiler would complain as soon as you tried to call the method statically in any case.
² Actually, this is not always true. For example, the C# compiler will not let you define extension methods in a non-static class -- not because it cannot, but because it wants to nudge you towards a "best practice".
static class cannot have non-static methods. If that's what you want - then use it.
More information can be found in this SO question and answers.