I just tried something to better understand access levels. In documentation for tuple's access level , there is a description from:
The access level for a tuple type is the most restrictive access level of all types used in that tuple.
Tuple types don’t have a standalone definition in the way that classes, structures, enumerations, and functions do. A tuple type’s access level is determined automatically from the types that make up the tuple type, and can’t be specified explicitly.
As I understand from this : A tuple type’s access level is determined automatically from the types that make up the tuple type, and can’t be specified explicitly.
So if i declare a tuples lik:
var tuples = (private access level , public access level)
Above tuples's access level must be private
right?
When I try below code:
public class Main{
var value1 : Int = 4
}
fileprivate class Main2{
var value2: Int = 4
}
private class Main3{
var value3 : Int = 4
}
public class tupleExample {
var tupleIs = (Main(),Main2(),Main3()) // this tupleIs's access level is internal here
}
Compiler gives me this error : Property must be declared fileprivate because its type '(Main, Main2, Main3)' uses a private type
I can fix this by adding access level to tupleIs
property
fileprivate var tupleIs = (Main(),Main2(),Main3())
But , as stated in the definition , A tuple type’s access level is determined automatically from the types that make up the tuple type, and can’t be specified explicitly.
So compiler must be add private
for tupleIs
access level because most restrictive access level is private
but it gives me an error.
My question is why I am getting a compiler error for this situation. Am i forgetting/missing somewhere?
You are mistaking the access level of a tuple property that you declare on a custom type with the access level of the individual elements of the tuple.
The quote in your question refers to the access level of the individual elements of the tuple. Meaning that in your example, var tuple = (Main(),Main2(),Main3())
, where Main
is public
, Main2
is fileprivate
and Main3
is private
, the access levels of the tuple elements will match that of their types:
tuple.0
will implicitly be public
, since its element, Main
is a public
typetuple.1
will implicitly be fileprivate
, since its element, Main2
is a fileprivate
typetuple.2
will implicitly be private
, since its element, Main33
is a private
typeIf you were to use a struct instead of the tuple with the following 3 properties, you'd also need to apply at least as restrictive access levels as the types of the properties:
public struct Example {
// This could be more restrictive than public (internal, file private, private)
public let publicProperty: Main
// This cannot be less restrictive than fileprivate, but can be more restrictive (private)
fileprivate let fileprivateProperty: Main2
// There is no more restrictive access control level than private, so this can only be private
private let privateProperty: Main3
}
However, when declaring the tuple
property on a custom type, you can control the access level of that property.
public class tupleExample {
public var tupleIs = (Main(),Main2(),Main3())
}
Same as if you were to declare the property with the struct
type
public class tupleExample {
public let example: Example
}
But in either case, you will only be able to access the properties of the type (or the elements of the tuple) based on their own access level, not based on the access level of the enclosing type.
So in case of the tuple example
public class tupleExample {
public var tupleIs = (Main(),Main2(),Main3())
func accessProperties() {
// Even though your `tupleIs` is accessible from outside the module, since it is public, not all of its properties are accessible outside the module
print(tupleIs.0) // this is allowed from outside the module, since Main is public
print(tupleIs.1) // this is only allowed inside the file, since Main2 is file private
print(tupleIs.2) // this won't even compile, since you're trying to access a private property from outside its type
}
}
And the same with the struct
:
public class tupleExample {
public let example: Example
func accessProperties() {
// Even though `example` is accessible from outside the module, since it is public, not all of its properties are accessible outside the module
print(example.publicProperty) // this is allowed from outside the module, since the property is public
print(example.fileprivateProperty) // this is only allowed inside the file, since the property is fileprivate
print(example.privateProperty) // this won't even compile, since you're trying to access a private property from outside its type
}
}
TLDR: So the big difference between the access level of a tuple vs a custom type (class
or struct
) is that in a custom type, you can explicitly specify the access level of the property, but it has to be at least as restrictive as the type of the property. On the other hand, with a tuple, the access level of the elements of the tuple are all implicitly matching the access level of the element's type - you cannot make it more restrictive.