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.
Related
What is the reason of using custom getters and setters in an application.
That's fairly very simple
First let me show you a sample of how getters and setters in Dart look like, which is essentially the language behind Flutter
class Foo {
// Creating a field/instance variable
String _fooName; //Keeping it private always
// Using the getter
String get foo_name {
//We can do something else here, like saving the variable somewhere and then returning it to the caller function
return _fooName;// private variable return for use in outside class
}
// Using the setter method
set foo_name (String name) {
// We can do something else, like update another variable based on fooName
this._fooName = name;//private variable being assigned new value
}
}
From the name, setters are involved in setting the values to an instance variable in an object oriented programming paradigm whereas getters are involved in getting the value of an instance variable
Now you would ask why not return the instance variable directly and why having such a roundabout approach to setting and getting the value
Well the answer is while getting as well as setting, we might want to do some other operation too other than just setting or getting the value and it's always better not to give admin access to the variables and that's why they are private so as to promote consistency within the objects accessing the field
It's a matter of preference, but you really shouldn't needlessly create one for a single field
https://dart.dev/guides/language/effective-dart/usage#dont-wrap-a-field-in-a-getter-and-setter-unnecessarily
One use case for creating a setter would be to perform some type of validation
For a getter, it'd be useful for a calculated field based on other properties, rather than a single property alone
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 have created a custom class and I want to add associated getters and setters. I have read the official documentation from Apple and notice that when setting a getter and setter, you actually create a separate variable, which seems really confusing. For instance, in the documentation linked above, getters and setters are applied to a new variable called perimeter to obtain values from another variable called sidelength. Below is my code:
Getters and setters like you are implementing them are only used for computed variables in Swift. A variable with a getter and setter doesn't actually store anything, but does something when assigned or used for its value with other variables. When appropriate to use, the usage would be more like this.
var _key: String?
var key: String? {
get {
return _key
}
set {
_key = newValue
}
}
You would rarely if ever use this on an identical data type though. I use these for communication with CoreData often, and setting things like dates as a string or back to a date. Occasionally I might use it to handle the change in an optional to a non optional.
Getters and setters are not needed in order to use the variable in Swift though. If you are used to languages with them, I can understand the confusion here, but forget the correlation and start over with how you think about it. I am sure after a short amount of time, you will like the way Swift works with its datatypes!
Edit:
In order to do what you want, all you need is this:
class PollCell: UICollectionViewCell {
var key: String?
}
Now you can assign any value you want to cell.key and retrieve any value you want from cell.key.
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)
}
}
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() {
}