What is the difference between "let" and "static let"? [duplicate] - swift

This question already has answers here:
Differences between "static var" and "var" in Swift
(3 answers)
Closed 6 years ago.
class Foo {
let fooValue = 1
}
print(Foo.fooValue) // not work
class Bar {
static let barValue = 1
}
print(Bar.barValue) // work; print "1"
Why? I expected that Foo example to work, because the value of fooValue is constant, value and memory address known in compilation time. But I need use keyword static to work.

fooValue is an instance property. There's one separate fooValue per every instance (object) of the Foo class.
barValue is a static property. There's one shared barValue that belongs to the class.
Here's a more concrete example. Suppose I had this class:
class Human {
static let numberOfLimbs = 4
let name: String
}
What would you expect to happen if I asked you what the name of a Human is? I.e. Human.name. Well, you wouldn't be able to answer me, because there's no one single name of all humans. Each human would have a separate name. You could however, tell me the number of limbs humans have, (Human.numberOfLimbs), which is (almost) always 4.

you don't have to instantiate your class to access static properties
if you wanted to access it in your first class use
Foo().fooValue
generally you want to use static for properties that you want to access without having to instantiate the object every time

Related

What is difference between create object with init and () in Swift [duplicate]

This question already has answers here:
In Swift, what's the difference between calling UINavigationController() vs UINavigationController.init()?
(3 answers)
Closed 5 years ago.
class A {
private var value: Int
init(value: Int) {
self.value = value
}
}
We have class A and what is the difference between I create this object by using A.init(value: 5) and A(value: 5)? Thanks
There is no functional difference between the two. Both styles will call the same initializer and produce the same value.
Most style guides that I've seen prefer to leave out the explicit .init-part in favor of the shorter A(value:) syntax — that also resembles the constructor syntax in many other languages.
That said, there are some scenarios where it's useful to be able to explicitly reference the initializer. For example:
when the type can be inferred and the act of initialization is more important than the type being initialized. Being able to call return .init(/* ... */) rather than return SomeComplicatedType(/* ... */) or let array: [SomeComplicatedType] = [.init(/* ... */), .init(/* ... */)]
when passing the initializer to a higher order function, being able to pass "something".map(String.init) rather than "something".map({ String($0) })
Again, it's a matter of style.

Swift static property initilizers are lazy why I could declared it as a constant

As far as I known (see reference A), Static property initilizers are lazy, and I found the following description by the office documents
You must always declare a lazy property as a variable (with the var
keyword) because its initial value might not be retrieved until after
instance initialization completes. Constant properties must always
have a value before initialization completes, and therefore cannot be
declared as lazy.
From the above information, I think I couldn't define the static property as a constant variable and I made a tryout, it turns out I can do that without triggering any error from the compiler.
Example:
class Person {
static let firstNaID = "First Name"
static let lastNaID = "Last Name"
}
Question: Is this a bug of the Swift 3.0.1 or I was wrong.
Reference A: Neuburg. M.2016. IOS 10 Programming Fundamental with Swift. P127
Thanks for your time and help
Neuburg M. is drawing a distinction between static properties and instance properties. You are pretending to ignore that distinction. But you cannot ignore it; they are totally different things, used for different purposes.
In this code:
class Person { // let's declare a static property
static let firstNaID = "First Name"
}
... firstNaID is already lazy. But now try to do this:
class Person { // let's declare an instance property
lazy let firstNaID : String = "First Name" // error
}
You can't; as things stand (up thru Swift 3.1), you have to say lazy var instead — and when you do, you get a lazy instance property.
Your static let declaration thus doesn't accomplish what lazy let wanted to accomplish, because a static property is not an instance property.
You are talking about type properties
Form the same chapter of the documentation
Type Properties
... Type properties are useful for defining values that are universal to all instances of a particular type, such as a constant property that all instances can use ...
Stored type properties can be variables or constants. Computed type properties are always declared as variable properties, in the same way as computed instance properties.
NOTE
...
Stored type properties are lazily initialized on their first access. They are guaranteed to be initialized only once, even when accessed by multiple threads simultaneously, and they do not need to be marked with the lazy modifier.

Swift: get the compile time name of variable (referencing to a class)

Is there a way to get the compile time name of a variable in Swift 2?
I mean the first variable name, which references to a new class instance, if any.
Here is a simple example:
public class Parameter : FloatLiteralConvertible {
var name:String?
var value:Double
// init from float literal
public required init (floatLiteral value: FloatLiteralType) {
self.value = Double(value)
self.name = getLiteralName()
}
func getLiteralName () -> String {
var literalName:String = ""
// do some magic to return the name
return literalName
}
}
let x:Parameter = 2.0
print(x.value) // this returns "2.0"
print(x.name!) // I want this to return "x"
I've already checked similar questions on that topic handling mirroring or objective-c reflections. But in all those cases, one can get only the property names in a class - in the example above name and value.
The same question has been asked in 2014 - Swift: Get Variable Actual Name as String
- and I hope, that since then there is a solution in swift 2.
No, there is no way to do that.
You have to understand that in the compiled state that variable usually does not exist. It can be optimized out or it is represented only as an item on the execution stack.
Even in languages with much better reflection that Swift has, usually you cannot inspect local variables.
To be honest, getting the name of a local variable dynamically has no practical use case.

Which do you use 'obj' or 'self.obj'? [duplicate]

This question already has answers here:
When should I access properties with self in swift?
(6 answers)
Closed 7 years ago.
I have a trivial question.
Which do you use A or B in this case? Why?
obj and self.obj are exactly the same.
let obj = MyClass()
func sampleFunction(obj: MyClass) {
// A
obj.xxx()
// B
self.obj.xxxx()
}
self.obj refers to the instance of the class you are in and access the obj instance variable defined. Referring to obj will refer to the named parameter within the scope of the function.
class Test {
let obj = "Global"
func sampleFunction(obj: String) {
// A
print(obj)
// B
print(self.obj)
}
}
var t = Test()
t.sampleFunction("Internal")
Paste this into a Playground for a demo of this to aid the explanation.
It is subjective whether or not to use self to refer to instance variables, but if there is another local variable or named parameter with the same name as the instance variable in that scope - you must use self to differentiate like in the example.
It is a good rule-of-thumb to always use self to refer to instance variables, this improves readability and decreases the chance of bugs relating to conflicting local variable names in scope occurring.

Defining stored type properties on classes [duplicate]

This question already has answers here:
Stored type properties for classes in Swift
(2 answers)
Why no stored type properties for classes in swift?
(3 answers)
Closed 7 years ago.
I'm a Swift rookie and found myself confused when reading this paragraph from "The Swift Programming Language" reference book (on Language Guide > Properties > Type Properties):
“For value types (that is, structures and enumerations), you can define stored and computed type properties. For classes, you can define computed type properties only.”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/br/jEUH0.l
But a couple of pages after this, the following code snippet can be found:
...
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
// return an Int value here
}
class var overrideableComputedTypeProperty: Int {
// return an Int value here
}
}
...
Where a stored type property is clearly defined inside a class context, which apparently negates what was stated earlier.
So, is this a documentation error or am I just missing something?
Edit 1
I don't feel like this is a duplicate from this question. I'm not asking why this functionality is not implemented, because apparently it is currently implemented (since the compiler won't identify it as an error). All I'm asking is if the documentation os out of date or my interpretation is incorrect.
Edit 2
This issue was addressed here. Apparently the documentation is out of date. This functionality was added on Swift 1.2
I believe what the documentation meant (in a rather confusing way) is that you cannot have class stored vars (while you can still have static stored vars).
So, to summarize
class Foo {
static var bar: Int { // ok (computed static type variable)
return 2
}
static var foo = "" // ok (stored static type variable)
class var foobar: Int { // ok (computed class type variable)
return 2
}
class var baz = "" // nope (stored class type variable)
}