Why does a public class/struct in Swift require an explicit public initializer?
Marking a class public does not necessarily imply that the developer wants the class to be initialized publicly. For example, I often write base classes that exist solely for me to be able to subclass them. I give these superclasses internal
initializers so that their subclasses can access them, but those in the outside world shouldn't be using them directly. For example, Operation
in Foundation
has no accessible initializers, yet the class is public. It is simply meant to be subclassed. This is considered an abstract class in Objective-C.
Since Swift doesn't contain explicit support for abstract classes, the act of making a class public but without public initializers basically serves as an abstract class (except each function must still have a default definition, either in the class itself or some protocol extension).
With this in mind, here are some Swift rules:
- If your class is marked
private
, all variables, inits, and functions will default toprivate
. - If your class is marked
internal
(which is default),public
, oropen
, all variables, inits, and functions will default tointernal
. - A subclass's superclass must be at least as accessible.
- classes and class members declared
public
in Objective-C are imported into Swift asopen
, due to there being no such distinction in Objective-C.
That second one is the one you are running into. The default init is picking up the default internal
because the last thing Swift wants to do is expose your init as public API unless it is explicitly instructed to do so.
Note: In my tests (at least in the playground), it seems that with the introduction of fileprivate
:
- If a class is declared
private
orfileprivate
, it seems that class members default tofileprivate
unless explicitly annotatedprivate
.
How can I make the memberwise initialiser public, by default, for structs in Swift?
Quoting the manual:
"Default Memberwise Initializers for Structure Types
The default memberwise initializer for a structure type is considered private if any of the structure’s stored properties are private. Otherwise, the initializer has an access level of internal.As with the default initializer above, if you want a public structure type to be initializable with a memberwise initializer when used in another module, you must provide a public memberwise initializer yourself as part of the type’s definition."
Excerpt from "The Swift Programming Language", section "Access Control".
Why do I need to write initializer for struct in Swift in order to use it in unit tests?
This is fixed in Swift 2.0 with the @testable
attribute.
If you import your module into the tests with @testable
the synthesized initializers will become visible to your tests.
You can find a brief intro to @testable
here.
Why Swift class need init but not Swift struct
Structs still have an initializers. The only differences is that in some cases the compiler will synthesize a "default member-wise initalizer" for you.
In this case, it created one with the signititure private init(value: Int)
(private
because your struct has a private
field)
What is the meaning of public init() { } in Swift 3?
When you mark public
, the thing gets available outside of the framework in which your code has been implemented whereas init() {}
is a swift initializer that is responsible for ensuring the object is fully initialized. Basically initializers are called to create a new instance of a particular type. In its simplest form, an initializer is like an instance method with no parameters.
init() {
// perform some initialization here
}
Related Topics
Get Path to Swift Script from Within Script
Exclude Swiftui Previews from Code Coverage
iOS 13.1 Uitextview Delegate Method Shouldinteract Called When Scrolling on Attachment
How Does Optional Covariance Work in Swift
What's a Good Way to Iterate Backwards Through the Characters of a String
Optional Chaining with Swift Strings
Swiftui: How Do Style Text View with Different Font and Colour on String Subranges
Swift: How to Expand a Tilde in a Path String
Swift Combine - Wait for All Publishers
How to Sort Objects by Its Enum Value
The Correct Way to Override an Initializer in Swift 1.1
Two Weak Variables Referencing Each Other in Swift
Swift Arc4Random_Uniform(Max) in Linux
How to Set an Ordered Relationship with Nspersistentcloudkitcontainer
Swift 3: How to Pinch to Scale and Rotate Uiimageview
Bitwise Operations with Cgbitmapinfo and Cgimagealphainfo