When should I assign value to properties in swift?
What is the difference between
class Thing {
var something:String = "Cool Thing"
}
and this
class Thing {
var something:String
init(){
something = "Cool Thing"
}
}
Actually its quite obvious when value is assigned on init() but when is value assigned when using 1st piece of code and which is the right way to do?
They're the same, but Apple suggests using the default property value pattern "if a property always takes the same initial value" for stylistic reasons. See the note in Default Property Values section of The Swift Programming Language: Initialization, which says:
Default Property Values
You can set the initial value of a stored property from within an initializer, as shown above. Alternatively, specify a default property value as part of the property’s declaration. You specify a default property value by assigning an initial value to the property when it is defined.
NOTE: If a property always takes the same initial value, provide a default value rather than setting a value within an initializer. The end result is the same, but the default value ties the property’s initialization more closely to its declaration. It makes for shorter, clearer initializers and enables you to infer the type of the property from its default value. The default value also makes it easier for you to take advantage of default initializers and initializer inheritance, as described later in this chapter.
You can use any of the 2. The difference is that if you have multiple initializer you might need to replicate the property initialization. Besides that it's just a matter of preference.
They should both be doing the same thing. The main difference for not initializing first would be if you wanted to assign the var as an optional and test for nil. Otherwise assigning the value would be the same.
var something:String?
Related
I am learning dart and this behavior of dart is annoying me
var a=10;
a="John"; //it generates an error, because a has integer data-type and we can't assign
//string or the value of any other data type because we have assigned an
//integer value
but at the same time, dart allows us to write
var a;
a=10;
a="John";
print (a) //it displays John
it means that we can't assign the value of any other data type when a variable initializes at the time of declaration but we can assign the value of any other data type if the variable declares in one line and initializes at the second line. Why does dart work in this way?
The var keyword is used to let Dart automatically assign a type for the variable based on the value you are using to initialize the variable.
If you use var without providing any initial value, the type of your variable are automatically being assign to dynamic which allows any type of object to be assigned to the variable. But it also means your program are much less type safe since the analyzer can no longer help you with what type the variable are going to return and what types are allowed when setting the variable.
So in your first example, a is being assigned the type int since you provide 10 as the initial value. It is therefore a compile error when you are trying to set a String as the new value of your int variable.
In your second example, a is going to be dynamic since you are not providing any initial value. So it is not a problem to first give it 10 and later 'John' since dynamic allow us to use any type. But that also means that when we try to use a in our program, Dart cannot make any guarantees about what type of object you are going to get so errors will first be identified at runtime.
That's because var means dart will assign the type of variable itself.
In first case, the dart assigned variable a as int type because it was given a value during initialisation.
But in second case, the dart assigned variable a as dynamic and that's why you can assign it either a string or int later on.
What's the preferred way of getting a value in swift?
Using a read-only variable
var getString: String? {
return "Value"
}
or using a function?
func getString() -> String? {
return "Value"
}
Also, is there a performance difference between the two?
First, neither of these would be appropriate names. They should not begin with get. (There are historical Cocoa meanings for a get prefix that you don't mean, and so even if you mean "go out to the internet and retrieve this information" you'd want to use something like fetch, but certainly not in the case you've given.)
These issues are addressed in various sections of the Swift API Design Guidelines. First, a property is a property, whether it is stored or computed. So there is no difference in design between:
let someProperty: String?
and
var someProperty: String? { return "string" }
You should not change the naming just because it's computed. We can then see in the guidelines:
The names of other types, properties, variables, and constants should read as nouns.
Furthermore, as discussed in The Swift Programming Language:
Properties associate values with a particular class, structure, or enumeration. Stored properties store constant and variable values as part of an instance, whereas computed properties calculate (rather than store) a value.
So if this is best thought of as a value associated with the type (one of its "attributes"), then it should be a property (computed or stored). If it is something that is not really "associated" with the type (something that the caller expects this type to retrieve from elsewhere for instance), then it should be a method. Again from the Design Guidelines:
Document the complexity of any computed property that is not O(1). People often assume that property access involves no significant computation, because they have stored properties as a mental model. Be sure to alert them when that assumption may be violated.
If "stored properties as a mental model" doesn't match what you mean to express, then it probably shouldn't be a property in the first place (and you need to document the discrepancies if you make it a property anyway). So, for instance, accessing a property should generally have no visible side effects. And if you read from a property immediately after writing to it, you should get back the value you wrote (again, as a general mental model without getting into the weeds of multi-threaded programming).
If you use a method, it can often result in a different appropriate name. See the "Strive for Fluent Usage" section of the Design Guidelines for more on that. There are several rules for selecting good method names. As a good example of when to use properties vs methods, consider the x.makeIterator(), i.successor() and x.sorted() examples and think about why these are methods and why they're named as they are. This is not to say there is exactly one answer in all cases, but the Design Guidelines will give you examples of what the Swift team intends.
With no discernible difference in performance, make the choice for readability:
When an attribute behaves like a variable, use a property. Your example falls into this category.
When reading an attribute changes object state, use a function. This includes
Attributes that behave like a factory, i.e. returns new objects when you access them
Attributes that produce new values, such as random number generators
Peripheral readers
Input iterators
Of course, if the attribute is computed based on one or more argument, you have no other choice but to use a function.
Just as a note: If you want to use both getters and setters in Swift you can do as follows:
var myString: String {
get {
return "My string"
}
set {
self.myPrivateString = newValue
}
}
This way you can access your value as if it was a regular variable, but you can do some "under-the-hood magic" in your getters and setters
First of all, I believe my question is different with those questions about "what is optional in swift". Because I am asking why I can do this, not what is this.
I am new to swift. When I learn this fabulous language tonight, I got a problem that I never saw this mark-"?" in a programming language. And I searched it for a while. I know what optional binding is now.
But now I got a new question.
When I want to declare a variable that is not optional. I can write this syntax:
var friend: String
But I can't write:
var friend: String = nil
To declare a variable that is nil I can only use optional:
var friend: String? = nil
Let's see the first piece of code. When the new variable friend just be declared, its value is nil, right? Because I didn't assign any value to it. But according to the definition of optional, like the second and the third pieces of code, we can't assign nil to non-optional variables.
So my question is why I can declare a variable without optional mark but has no initial value. This question may be simple, but I really don't know why it happens.
Thanks in advance!
Swift allows you to declare a non-optional variable or constant without initializing it in the declaration, but you will have to assign it a value before using it. The value of the variable or constant is not nil (non-optionals can never be nil)--it simply has no defined value. Basically you are saying you will give it a value later, possibly based on the result of a computation or an if statement.
Swift will give you a compile-time error if you try to use a non-optional variable or constant without first assigning a value to it.
The first value you set is an uninitialized variable with the type of string.
A very common pattern in programming is to have an operation that might or might not return a value. In some languages, like javascript, when coming across a null value our program continues to operate just fine as long as our program is not dependent on that value to continue. In other languages, like java for example, a null value can cause a NullPointerException and crash our program.
Swift's solution to this problem is optionals. By default if we define a variable without a value, the compiler will complain. So, in order to declare a value that may or may not have a value at runtime, we need to add a ? which is known as “wrapping our values in an optional”. This is because we are indeed literally wrapping our value in Swifts optional type, thus giving it value. To get a better picture as to whats going on, we can look at how Swifts Optional enum.
enum Optional<T> {
case None // has no value
case Some(T) // has some value
}
I'm just wondering. As I understand, var and let can be anything and Swift automates the right type like in JavaScript. But when I try to set properties in a class I get an error when I don't specify the type.
var value1, value2 // Error: missing annotations
Well, I've read some references and the variable requires a type on declaration like var foo = 0. But in my class I have an init() which will set the variables to whatever I input when creating the object of the class.
So how should I achieve this? Is it even possible?
I saw the type typealias but that didn't work either.
While both Swift and Javascript allow you to assign constants to variables without defining their type, there is a fundamental difference in the two languages. Swift is a strongly-typed, type-safe language while Javascript is not. From The Swift Programming Language -
“Swift is a type safe language. A type safe language encourages you to
be clear about the types of values your code can work with. If part of
your code expects a String, you can’t pass it an Int by mistake.”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks.
https://itunes.apple.com/au/book/swift-programming-language/id881256329?mt=11
So when you say
var welcomeMessage = "Hello"
Swift infers that you want welcomeMessage to be a string and sets its type accordingly. Subsequently trying
welcomeMessage=3
will give run a compile-time error because you are assigning the incorrect type.
If you don't assign an initial value then Swift can't infer the type and you must specify it.
Javascript, on the other hand, will quite happily accept
var welcomeMessage="Hello"
welcomeMessage=3
because it isn't type safe and just tries to do the best it can with values it has. For example, if a string operation is performed on welcomeMessage after assigning 3 to it, Javascript would convert the value to "3" and then perform the operation.
While there are type safe extensions to Javascript, it isn't a fundamental part of the language the way it is with Swift
The types are only inferred if you assign a default value initially. From an example in the Language Reference, either declare the type:
var welcomeMessage: String
or assign an initial value that allows Swift to infer the type:
welcomeMessage = "Hello"
In the welcomeMessage example above, no initial value is provided, and so the type of the welcomeMessage variable is specified with a type annotation rather than being inferred from an initial value.
JavaScript is dynamically typed, meaning variables don't have a type assigned to them. Types are only associated with objects. So a variable can contain objects of any type.
Swift is statically typed on the other hand. Meaning variables have type. You can't place any object you want into a variable. The compiler will make sure you only place compatible objects into variables.
Swift has type inference which allow the compiler to figure out the type if you write:
var value1 = "foobar"
But just writing var value1 wouldn't let the compiler figure out what type the value1 variable is. JavaScript doesn't have this problem since variables don't have types.
Remember similar looking syntax does not mean the same semantics. Swift might look a bit like JavaScript syntax wise, but the meaning (semantics) of the keywords is quite different. If you want to simulate JavaScript:
var value1, value2
In Swift you would write:
var value1: AnyObject
var value2: AnyObject
That would allow you to put any object into the value1 and value2 variables.
I want to use a custom setter to do some formatting of my fields. In irb if I test the setter like:
o.field_name = "4"
I see that my custom setter is being referred to. But with this it is not:
o[:field_name] = "4"
I understand that in the first case this is a function call and in the second case we are just setting the attribute directly. But I don't completely see how the attribute can be set without going through our custom setter, I thought that was the point.
But my main question is that if var holds my field_name, I don't see how to dynamically refer to a.var and have it be interpreted as a.field_name. All I see to do is a[var] and this bypasses my setter.
Try a.send(var) where var = 'field_name'
That's the equivalent of a.field_name
o[:field_name] is like read_attribute(:field_name), thus is just reads the value as you said. It can be quite important in virtual attributes in order to bypass the stack too deep error. If you do a[:var], you just get its value. A virtual attribute refers to an attribute, if you are setting its value to another variable, you just get its value, not the object.