Playing around with Swift, coming from a Java background, why would you want to choose a Struct instead of a Class? Seems like they are the same thing, with a Struct offering less functionality. Why choose it then?
相关问题
- What uses more memory in c++? An 2 ints or 2 funct
- “Zero out” sensitive String data in Swift
- SwiftUI: UIImage (QRCode) does not load after call
- Get the NSRange for the visible text after scroll
- UIPanGestureRecognizer is not working in iOS 13
相关文章
- Using if let syntax in switch statement
- Enum with associated value conforming to CaseItera
- Swift - hide pickerView after value selected
- Is there a Github markdown language identifier for
- How can I vertically align my status bar item text
- Adding TapGestureRecognizer to UILabel in Swift
- Attempt to present UIAlertController on View Contr
- Swift - Snapshotting a view that has not been rend
Assuming that we know Struct is a value type and Class is a reference type.
If you don't know what a value type and a reference type are then see What's the difference between passing by reference vs. passing by value?
Based on mikeash's post:
In addition don't use class when you have to override each and every instance of a function ie them not having any shared functionality.
So instead of having several subclasses of a class. Use several structs that conform to a protocol.
Since struct instances are allocated on stack, and class instances are allocated on heap, structs can sometimes be drastically faster.
However, you should always measure it yourself and decide based on your unique use case.
Consider the following example, which demonstrates 2 strategies of wrapping
Int
data type usingstruct
andclass
. I am using 10 repeated values are to better reflect real world, where you have multiple fields.Performance is measured using
Code can be found at https://github.com/knguyen2708/StructVsClassPerformance
UPDATE (27 Mar 2018):
As of Swift 4.0, Xcode 9.2, running Release build on iPhone 6S, iOS 11.2.6, Swift Compiler setting is
-O -whole-module-optimization
:class
version took 2.06 secondsstruct
version took 4.17e-08 seconds (50,000,000 times faster)(I no longer average multiple runs, as variances are very small, under 5%)
Note: the difference is a lot less dramatic without whole module optimization. I'd be glad if someone can point out what the flag actually does.
UPDATE (7 May 2016):
As of Swift 2.2.1, Xcode 7.3, running Release build on iPhone 6S, iOS 9.3.1, averaged over 5 runs, Swift Compiler setting is
-O -whole-module-optimization
:class
version took 2.159942142sstruct
version took 5.83E-08s (37,000,000 times faster)Note: as someone mentioned that in real-world scenarios, there will be likely more than 1 field in a struct, I have added tests for structs/classes with 10 fields instead of 1. Surprisingly, results don't vary much.
ORIGINAL RESULTS (1 June 2014):
(Ran on struct/class with 1 field, not 10)
As of Swift 1.2, Xcode 6.3.2, running Release build on iPhone 5S, iOS 8.3, averaged over 5 runs
class
version took 9.788332333sstruct
version took 0.010532942s (900 times faster)OLD RESULTS (from unknown time)
(Ran on struct/class with 1 field, not 10)
With release build on my MacBook Pro:
class
version took 1.10082 secstruct
version took 0.02324 sec (50 times faster)Answering the question from the perspective of value types vs reference types, from this Apple blog post it would appear very simple:
As mentioned in that article, a class with no writeable properties will behave identically with a struct, with (I will add) one caveat: structs are best for thread-safe models -- an increasingly imminent requirement in modern app architecture.
With classes you get inheritance and are passed by reference, structs do not have inheritance and are passed by value.
There are great WWDC sessions on Swift, this specific question is answered in close detail in one of them. Make sure you watch those, as it will get you up to speed much more quickly then the Language guide or the iBook.
Structs
arevalue type
andClasses
arereference type
Use a
value
type when:Use a
reference
type when:Further information could be also found in the Apple documentation
https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
Additional Information
Swift value types are kept in the stack. In a process, each thread has its own stack space, so no other thread will be able to access your value type directly. Hence no race conditions, locks, deadlocks or any related thread synchronization complexity.
Value types do not need dynamic memory allocation or reference counting, both of which are expensive operations. At the same time methods on value types are dispatched statically. These create a huge advantage in favor of value types in terms of performance.
As a reminder here is a list of Swift
Value types:
Reference types:
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:
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:
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.