This question already has answers here:
Cannot assign property in method of struct
(2 answers)
Closed 7 years ago.
I'm studying swift and I'm trying to understand the difference between classes and struct, which as I understand it, is in these two points:
1) Classes are reference types, Whereas structures are value types. That means That When you pass an instance of a structure to a function, return an instance from a function, or assign the value of a variable That Refers to a structure to another variable, the instance is copied. In other words, structures exhibit pass-by-value behavior. Swift strings, arrays, and dictionaries are all Implemented as structures.
By contrast, class instances are passed by reference-no copy is taken.
2) Classes can be subclassed to add behavior; structures can not.
why these two errors?
depends on the structure ?, because a class does not give me the same error.
The reason you're getting those errors is that by default, the properties of a value type (i.e. a struct) cannot be modified from within its instance methods (e.g. your newRad() and plusOne() methods).
Related
This question already has answers here:
Difference between assigning the values in parameter list and initializer list
(2 answers)
Closed 2 years ago.
Flutter: The instance member'stars' can't be accessed in an initializer. Error
I asked the above question and received the following answer as the reason for the error.
reason : in dart you can't create a class level variable depends with
another variable
↑ Is there any explanation in the official Dart, Flutter document (or something similar)?
Or is it derived from the Dart constructor mechanism?
If so, I would like to understand how the constructor works, which is the reason for this error.
Is there any relevant part in the official Dart, Flutter documentation, etc.?
It is in fact due to Dart's constructor mechanism, specifically the order of execution during construction, as well as how Dart references instance variables within an object.
From the Instance Variables section of the Dart Language Tour:
If you initialize an instance variable where it is declared (instead of in a constructor or method), the value is set when the instance is created, which is before the constructor and its initializer list execute.
When you reference an instance variable in a Dart class via variableName there is an implied this reference to the instantiated object containing the variable. Due to the order of execution of Dart's object construction, this cannot reference the object during instance variable declaration because the object has not been created yet. Therefore, this.variableName and thus variableName (with implied this) cannot actually reference the instance variable.
This question already has an answer here:
How does a set determine that two objects are equal in dart?
(1 answer)
Closed 1 year ago.
I just stuffed a bunch of MyClass inside a Set in Dart. MyClass does not implement Comparable, and does not have an == operator defined. It compiled fine.
For this Set to detect duplicates properly, do I have to implement Comparable interface, or just override the == operator?
All Dart classes derive from Object, which does provide operator == and hashCode. Object's default implementations check for object identity; an instance of your class will compare equal only to itself.
If you want two different instances to be able to compare equal, then you need to:
Implement operator == and hashCode in your custom class. Set's default implementation is a LinkedHashSet, which does not use Comparable. (There is a SplayTreeSet implementation that does use Comparable, however, but lookup and insertions would be O(log n) instead of O(1).)
Alternatively use the LinkedHashSet constructor or the HashSet constructor and pass appropriate callbacks for equality and hash code computations.
This question already has an answer here:
Typecasting or initialization, which is better in Swift?
(1 answer)
Closed 6 years ago.
When stumbling across casting using "as! or as?", I also noticed that types could also be converted using the desired type inside of parenthesis such as:
let x : Int = 42
var myString = String(x)
This made me curious to ask if converting and casting are the same? However when I tried to do converting in a another example using a reference type, I don't think the compiler allows this or at least it gave me an error, such as:
let sutCast = storyboard.instantiateViewController(withIdentifier: "ItemListViewController") as! ItemListViewController
let sutConvert = ItemListViewController(storyboard.instantiateViewController(withIdentifier: "ItemListViewController"))
Is it safe to say or assume that in Swift, conversions are not allowed for reference types and casting is different from conversion because it depends if an object is a reference type or a value type?
From the documentation:
Type casting is a way to check the type of an instance, or to treat that instance as a different superclass or subclass from somewhere else in its own class hierarchy.
It is a way to convert one type to another but it can also be used for more, such as to check the type etc.
Refer to the documentation for more info.
I have this class in which the properties are the class itself.
class Voxel {
var vertices : [Vertex] = []
var above : Voxel?
var below : Voxel?
var front : Voxel?
var back : Voxel?
var left : Voxel?
var right : Voxel?
}
It acts as a node in a Doubly 3D Linked List, but the thing is, in C and C++, I would have to store the neighbors as pointers (which I want to do to the vertex array as well).
Is this automatically done for me in Swift?
I don't see a fine way of holding an array of vertices as an array of pointers, and I certainly don't want to hold the actual values, as I'm going to have thousands of voxels.
Because Voxel is a class, a reference type, these are pointers. If it were a struct, it would be a value type and therefore each new reference would be a new copy.
By the way, be wary of strong reference cycles. Make sure one instance's implicit strong reference below is not another instance whose above is another strong reference back to the other instance. To resolve this, you'd make all of those references weak and then have some collection (e.g., a set or maybe an array or dictionary) which maintains strong references to all of the instances in the doubly linked list.
The defining characteristic of classes (vs. structs) is that they're reference types, and use reference semantics (i.e. assignment of an object only copies a reference to the object).
Classes Are Reference Types
Unlike value types, reference types are not copied when they are assigned to a variable or constant, or when they are passed to a function. Rather than a copy, a reference to the same existing instance is used instead.
Structs, on the other hand, are value types, and use value semantics (i.e. assignment of a struct copies it entirely).
Structures and Enumerations Are Value Types
A value type is a type whose value is copied when it is assigned to a variable or constant, or when it is passed to a function.
I suggest you give this a read: The Swift Programming Language (Swift 2.2)
- Classes and Structures
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does fast enumeration not skip the NSNumbers when I specify NSStrings?
I noticed some unexpected behavior while using fast enumeration recently. In hindsight I was probably expecting fast enumeration to do more than it's intended for, so I'm looking for some clarification on how it's actually works.
Say I have a parent class Shape with 2 child classes, 3SidedShape and 4SidedShape. I have an array called myShapes, that contains objects from both the 3 and 4 sided classes.
If I wanted to search through the array myShapes, but I'm only concerned with 3 sides shapes what I was doing is:
for (3SidedShape *shape in myShapes)
My thought was that I would only be iterating over objects of class 3SidedShape, but that is not the case? I guess I'm casting all objects as 3SidedShape whether they like it or not. I'm evening returning the object after as a completely different class. Granted I'm not calling any methods that both classes don't have, but I didn't expect class siblings to just re-cast so easily without a hitch? Did I just get lucky here or can you really enumerate as any class you please regardless of relation? Can anyone explain what actually happens during enumeration?
The type specified in a for...in loop, aka fast enumeration, casts all the elements in the collection to the specified type. The reason why they are "re-cast so easily" is that casting does NOT turn one type of object into another (how would that work?). It's a hint to the compiler telling it to treat the object as if it were the other type, as if to say "don't worry, this object is of (insert type), so type check it as such." Sending the object a message it can't handle, but the type it was casted to can, will still crash the app. What you should do is this:
for (id shape in myShapes){
if ([shape isKindOfClass: [3SidedShape class]]){
//insert code here
}
}
That code assumes nothing of type, using introspection to only perform the code for objects who are of type 3SidedShape or a subclass of 3SidedShape. For exact checking (excluding subclasses) use isMemberOfClass:. Be wary of using isMemberOfClass: to test membership of a class in a class cluster (NSNumber), however, due to their more complex internal implementation.