fileprivate class someGenerics<T> where T: Equatable {
private var type:T?
func get(type: T) {
}
func someFunc<U>(unit: U) {
}
}
private T // error
fileprivate class someGenerics<T> where T: Equatable {
private var type:T?
func get(type: T) {
}
func someFunc<U>(unit: U) {
}
}
private T // error
If you mean the access level of a generic parameter, T
, that is not possible. But it is also senseless, since generic parameters in universal types (generic types) are supposed to be provided by the consumer upon instantiation. Could you share what you're trying to achieve by doing so, so we can help you?
If you want some members of the class to be generic, but not the class itself, use generics on those members, i.e.
class Foo {
func get<T>(type: T) where T: Equatable {...}
}
I don't understand the description of access control of generic in the language guide.could you write a demo for below?
Generics
The access level for a generic type or generic function is the minimum of the access level of the generic type or function itself and the access level of any type constraints on its type parameters.
It means that if your, let's say, function is less accessible than the types used in its generic requirements, the access level of the function persists. Example:
public protocol P {...}
fileprivate func foo<T: P>(_ arg: T) {...}
// foo is obviously fileprivate despite P being public
The opposite case, when a type used in a generic requirement is less accessible, is simply illegal.
The documentation isn't clear enough about when this is true in terms of the language rules. But formally, although illegal in Swift, the statement is also correct in the case when a type used in a generic requirement is less accessible than the declaration. Naturally, you won't be able to use the declaration beyond the scope of that type's access level anyway.
Apologies for the editing, I realized it's more understandable this way.
The docs still read the following as of WWDC 2020 and Swift 5.2:
“The access level for a generic type or generic function is the minimum of the access level of the generic type or function itself and the access level of any type constraints on its type parameters.”
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 5.2).” Apple Books. The Swift Programming Language (Swift 5.7) on Apple Books
A quick example shows some of the weirdness that isn't fully captured in this statement:
private protocol myPrivateProtocol {
func foo() -> Void
}
fileprivate func doTheGenericDance<T: myPrivateProtocol>(withFoo: T) -> Void {
withFoo.foo()
}
The above compiled successfully: A case where the generic requirement is less accessible than the function's access.
So, it appears that the opposite case is not always illegal. It appears not, as there is a special exception for the relationship between private / file-private.
private
at file level is equivalent to fileprivate
.
At the file level, EDIT: @Jon_Shier beat me to it private
and fileprivate
are synonyms.
private
at file level is equivalent tofileprivate
.
Well, now that's useful knowledge! Thanks!
@Jon_Shier is there a mention in The Swift Programming Language of this fact? It seems useful and should probably be there, but I didn't come across it in the Access Control section.
Not that I can see, I haven't read that book in quite a while. You can request it be added by filing a bug with Apple.
Actually, TSPL calls out an important way in which they are not quite the same in this section:
The access control level of a type also affects the default access level of that type’s members (its properties, methods, initializers, and subscripts). If you define a type’s access level as private or file private, the default access level of its members will also be private or file private [respectively].
@Jumhyn based on this reading, are you saying the the equivalency of private
to fileprivate
wouldn’t necessarily hold true within a file for members of a type?
When you're dealing with explicit access control, private
and fileprivate
aren't equivalent in general:
struct A {
private var x = 0
fileprivate var y = 0
}
// Same file...
print(A().x) // Error
print(A().y) // Ok
After actually testing, though, it doesn't appear that the language behavior agrees with the excerpt I posted from TSPL:
private struct A {
var x = 0
private var y = 0
}
fileprivate struct B {
var x = 0
}
print(A().x) // Ok! (I.e., x is not actually private)
print(A().y) // Error
print(B().x)
EDIT: Reported as SR-13196.
Would a simple solution to this be a built-in accessControlLevel(of:)
function, similar to type(of:)
?
@Jon_Shier @Jumhyn Would it be more accurate to say that at the global level of a file, fileprivate
and private
are equivalent, but not in the general case? That seems more accurate to me.
"file level" and "global level of a file" are the same thing.
Ah - Yes, that does make sense Thanks again!
File scope variables are available anywhere in the file. private
variables are available in their scopes only. private let
and private var
variables are available anywhere in the file only.