Structure VS Class in Swift Language

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

  1. Yes, Protocols are effectively like interfaces

  2. Classes are classes, like in Java/Android, and pretty much any other language

  3. 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



Leave a reply



Submit