structure vs class in swift language
Here's an example with a class
. Note how when the name is changed, the instance referenced by both variables is updated. Bob
is now Sue
, everywhere that Bob
was ever referenced.
class SomeClass {
var name: String
init(name: String) {
self.name = name
}
}
var aClass = SomeClass(name: "Bob")
var bClass = aClass // aClass and bClass now reference the same instance!
bClass.name = "Sue"
println(aClass.name) // "Sue"
println(bClass.name) // "Sue"
And now with a struct
we see that the values are copied and each variable keeps it's own set of values. When we set the name to Sue
, the Bob
struct in aStruct
does not get changed.
struct SomeStruct {
var name: String
init(name: String) {
self.name = name
}
}
var aStruct = SomeStruct(name: "Bob")
var bStruct = aStruct // aStruct and bStruct are two structs with the same value!
bStruct.name = "Sue"
println(aStruct.name) // "Bob"
println(bStruct.name) // "Sue"
So for representing a stateful complex entity, a class
is awesome. But for values that are simply a measurement or bits of related data, a struct
makes more sense so that you can easily copy them around and calculate with them or modify the values without fear of side effects.
Why Choose Struct Over Class?
According to the very popular WWDC 2015 talk Protocol Oriented Programming in Swift (video, transcript), Swift provides a number of features that make structs better than classes in many circumstances.
Structs are preferable if they are relatively small and copiable because copying is way safer than having multiple references to the same instance as happens with classes. This is especially important when passing around a variable to many classes and/or in a multithreaded environment. If you can always send a copy of your variable to other places, you never have to worry about that other place changing the value of your variable underneath you.
With Structs, there is much less need to worry about memory leaks or multiple threads racing to access/modify a single instance of a variable. (For the more technically minded, the exception to that is when capturing a struct inside a closure because then it is actually capturing a reference to the instance unless you explicitly mark it to be copied).
Classes can also become bloated because a class can only inherit from a single superclass. That encourages us to create huge superclasses that encompass many different abilities that are only loosely related. Using protocols, especially with protocol extensions where you can provide implementations to protocols, allows you to eliminate the need for classes to achieve this sort of behavior.
The talk lays out these scenarios where classes are preferred:
- Copying or comparing instances doesn't make sense (e.g., Window)
- Instance lifetime is tied to external effects (e.g., TemporaryFile)
- Instances are just "sinks"--write-only conduits to external state (e.g.CGContext)
It implies that structs should be the default and classes should be a fallback.
On the other hand, The Swift Programming Language documentation is somewhat contradictory:
Structure instances are always passed by value, and class
instances are always passed by reference. This means that they are
suited to different kinds of tasks. As you consider the data
constructs and functionality that you need for a project, decide
whether each data construct should be defined as a class or as a
structure.As a general guideline, consider creating a structure when one or more
of these conditions apply:
- The structure’s primary purpose is to encapsulate a few relatively simple data values.
- It is reasonable to expect that the encapsulated values will be copied rather than referenced when you assign or pass around an
instance of that structure.- Any properties stored by the structure are themselves value types, which would also be expected to be copied rather than referenced.
- The structure does not need to inherit properties or behavior from another existing type.
Examples of good candidates for structures include:
- The size of a geometric shape, perhaps encapsulating a width property and a height property, both of type Double.
- A way to refer to ranges within a series, perhaps encapsulating a start property and a length property, both of type Int.
- A point in a 3D coordinate system, perhaps encapsulating x, y and z properties, each of type Double.
In all other cases, define a class, and create instances of that class
to be managed and passed by reference. In practice, this means that
most custom data constructs should be classes, not structures.
Here it is claiming that we should default to using classes and use structures only in specific circumstances. Ultimately, you need to understand the real world implication of value types vs. reference types and then you can make an informed decision about when to use structs or classes. Also, keep in mind that these concepts are always evolving and The Swift Programming Language documentation was written before the Protocol Oriented Programming talk was given.
What are the main differences between classes and structs in swift 3?
class Car {
var name: String
init(name:String){
self.name = name
}
}
var carA = Car(name: "BMW")
var carB = carA
//now I will change carB
carB.name = "Nissan"
print(carA.name) //This will print Nissan
struct CarStruct {
var name: String
init(name: String){
self.name = name
}
}
var carC = CarStruct(name: "BMW")
var carD = carC
//now I will change carB
carD.name = "Nissan"
print(carC.name) //This will print BMW
As you can see both CarA
and CarB
are pointing to the same reference so if one changes the other change because the reference is changing, while in CarC
and CarD
which are structs they are copies of each other each with its value.
I am confuse structure vs class in swift language
In swift class
is reference type. (see here)
When you say:
SB.obj = SA.obj
It means that the object of SA is the exact object in SB. (there is one pointer for SA.obj and SB.obj)
Although
let SB = SA
makes copy of SA and create SB with different reference.
What is the difference between Classes and Structures in Swift
- Class is a reference type, structure is a value type. It means that structs are copied when passed somewhere, whereas classes are passed by reference
- Inheritance. You can create a subclass that will inherit parent's properties and methods
- Deinitializers. Allow to perform cleanup before object is deallocated. Objects are usually deallocated when instance is no longer referenced by other code. More about ARC here.
- More than one reference to a class instance
You can get Apple's guide to Swift language here
For Swift language, what is the difference in initializing structs versus initializing classes? (I'm fairly new to programming)
A struct
will automatically generate an initializer for you to initialize all properties. A class
will not synthesize a constructor for you unless you give initial values to all properties (or use Optionals which are automatically nil
). In your case, you need to write your own initializer:
class PendingBinaryOperationInfo {
var binaryFunction: (Double, Double) -> Double
var firstOperand: Double
init(binaryFunction: (Double, Double) -> Double, firstOperand: Double) {
self.binaryFunction = binaryFunction
self.firstOperand = firstOperand
}
}
You should be careful replacing a struct
with a class
for data. It can lead to unexpected results since class
is a reference type and struct
is a value type.
Consider this example:
class Coord {
var x = 0
var y = 0
}
// Create an array with 5 Coords
var coords = [Coord](count: 5, repeatedValue: Coord())
coords[0].x = 13
print(coords[1].x) // prints "13"
In this case, the array coords
contains 5
references to the same Coord
object. So updating one updates them all.
If you change class
to struct
, then you will have 5
different values in the array and the result will print 0
.
How should I reason when I have to choose between a class, struct and enum in Swift?
ChristopheD's and Jack Wu's answers are good, but I feel they don't touch on enums, or miss their importance. Swift enums are (meant to be) a full implementation of algebraic data types. Classes and structs are traditionally used to model data in object-oriented languages, but enums are usually limited to being used as a convenient way to limit the value of a variable to a limited number of possibilities. E.g. (C++):
enum MaritalStatus { Unmarried, Married, Divorced, WidowedOrWidowered };
MaritalStatus m = Unmarried;
Swift enums can do the above but they can do a lot more. Of course the Language Guide has a pretty good barcode modelling example but the best example I know of that really drives home the point of modelling data with algebraic data types is Scott Wlaschin's presentation: http://www.slideshare.net/ScottWlaschin/ddd-with-fsharptypesystemlondonndc2013
You would probably benefit from going through the whole presentation but really to 'get' the point all you need to see is slide 60 where he shows how to model a 'payment method' in a typical line-of-business app.
The examples in the presentation are in F# but F# isn't that far off from Swift and you can pretty easily map between them. E.g., the payment methods enum in Swift would look like:
enum PaymentMethod {
case cash // No extra data needed.
case cheque(Int) // Cheque #.
case card(CardType, CardNumber) // 2 pieces of extra data.
}
The point of the above is that each order's payment method can be only one of the above three methods. Anything else will not be allowed by the compiler. This is a very succinct alternative to building entire class hierarchies to model these almost trivial things.
The presentation really takes off from there and the best part is Swift can do almost everything that F# can in terms of data modelling, using optional types, etc.
Swift: Protocol vs. Struct vs. Class
These analogies are not "exactly" correct, but this is the gist of it as I understand it
Yes, Protocols are effectively like interfaces
Classes are classes, like in Java/Android, and pretty much any other language
Structs are like classes, but they are passed by-value (copied) when passing them from one variable/function to another.
If you're familiar with C# at all, it's implementation of structs is very similar.
Eg:
class Foo {
...
}
let x = Foo()
let z = x
At this point x and z both refer to the same Object in memory, there is only one Foo
object
struct Bar {
...
}
let a = Bar()
let b = a
When assigning b, a is copied (think of basically copying the memory block). At this point, there are two independent Bar
objects in memory and modifying one doesn't affect the other.
Why is this useful? Sometimes you don't want a shared reference, but mostly for performance reasons. Because structs don't have to all refer to the same object, they don't have to be allocated on the heap. They can instead often be allocated on the stack, which is much faster. Also arrays of structs can be implemented as one big contiguous block of memory which means it's much friendlier on the CPU cache if you want to iterate through it all.
Swift isn't garbage collected, but for garbage collected languages like C# this can mean the garbage collector doesn't have to deal with a lot of objects that it might otherwise have to. Even in swift the struct copying means it can avoid doing the Retain
/Release
behind the scenes neccessary for ARC, which can help a lot.
The primary use case for structs is when you have lots of immutable "simple data" like a Vector (set of 3 floating point values)
Declare a structure which is inside a class
Your use case is a bit strange, the main reason for declaring an internal type within another type is that you want to use the internal type inside the outer type.
An example
class SubMain: Main {
var test: Test?
override init(name:String){
super.init(name: name)
}
convenience init(name: String, test: Test) {
self.init(name: name)
self.test = test
}
struct Test {
var number1:Int
var number2:Int
}
}
And then
var main2 = SubMain(name: "hello")
var main3 = SubMain(name: "world", test: .init(number1: 1, number2: 2))
But to use your example you should access it via the outer type and not an instance of that type
var test = SubMain.Test(number1: 1, number2: 2)
Related Topics
How Does One Generate a Random Number in Swift
Swift Protocol Extension Method Is Called Instead of Method Implemented in Subclass
Input from the Keyboard in Command Line Application
Understanding Spritekit Collisionbitmask
Swiftui Iterating Through Dictionary With Foreach
Calculate Age from Birth Date Using Nsdatecomponents in Swift
Using Dateformatter on a Unix Timestamp
Swift 3.0: Convert Server Utc Time to Local Time and Vice-Versa
Extra Arguments At Positions #11, #12 in Call Swiftui
How to Create Usdz File Using Xcode Converter
How to Add Type Constraints to a Swift Protocol Conformance Extension
Non-'@Objc' Method Does Not Satisfy Optional Requirement of '@Objc' Protocol
Get Integer Value from String in Swift