- Classes being "closed" by default is unusual in most OOP languages and allows for a careless developer to unknowingly write a library that restricts how it can be used by not making classes open as needed.
- Swift's distinction between file-private and declaration-private scopes is confusing (
fileprivate
andprivate
as of Swift 3) and completely unnecessary most of the time, since when one includes two top-level declarations in the same file, it's usually because the declarations are supposed to be visible to each other.
-
open
: all declarations are implicitly open; noopen
keyword. -
final
: inherits implicit visibility when none is specified.- Final classes cannot be subclassed (structs, enums, global funcs, etc are implicitly final).
- Final properties and methods cannot be overridden by subclasses.
-
public
: visible to every file in all modules. -
internal
: default visibility for top-level decls when none is specified.- Internal top-level declarations visible to same module only.
- Internal nested decls (properties, methods, inner types) visible to same file and subclasses ONLY (not applicable to structs), behaves like Java's
protected
keyword.
-
private
: visible to same file only.- Private type members are implicitly final.
Nested decls inherit parent decl visibility, except when the parent decl is public. All public members and types must be declared public explicitly. Members of an internal type are visible wherever the parent decl is visible.
// Implicitly internal and open.
class Foo {
// Visible where Foo is visible
var name = ""
// Visible ONLY to subclasses and same file
internal var id = 5
// Visible to same file only, implicitly open
private func bar() {}
// Error: conflicting visbility with parent decl
public func bar(_ x: Int) {}
// Visible to subclasses and same file, cannot be overridden.
internal final func cannotOverride() {}
}
// Implicitly open
internal class SameVisibilityAsFoo {
}
// Visible everywhere, not subclassable
public final class Bar {
// Implicitly internal and final
var name = ""
// Error: parent decl is final, use private instead.
internal var color = "red"
// Warning: `final` specifier is redundant
// when applied to member of a `final` type
private final var id = 5
}
// Visible to same file, implicitly open
private class Baz {
}
// Visible to all modules
public func abc() {}
// Implicitly internal, visible to whole module only
func def() {}
// Same as above
internal func ghi() {}
// Visible to same file only
private func jkl() {}