¿Cuál es un buen ejemplo para diferenciar entre fileprivate y private en Swift3?
142
Este artículo ha sido útil para comprender los nuevos especificadores de acceso en Swift 3. También da algunos ejemplos de diferentes usos de fileprivatey private.
Mi pregunta es: ¿no es lo mismo usar fileprivateuna función que se va a usar en este archivo que usar private?
fileprivateahora es lo que privatesolía ser en versiones anteriores de Swift: accesible desde el mismo archivo fuente. Una declaración marcada como privateahora solo se puede acceder dentro del ámbito léxico en el que se declara. Por privatelo tanto, es más restrictiva que fileprivate.
A partir de Swift 4, las declaraciones privadas dentro de un tipo son accesibles para extensiones del mismo tipo si la extensión se define en el mismo archivo fuente.
Ejemplo (todo en un archivo fuente):
class A {privatefunc foo(){}fileprivatefunc bar(){}func baz(){
foo()
bar()}}extension A {func test(){
foo()// Swift 3: error: use of unresolved identifier 'foo'
// Swift 4: no error because extension is in same source file
bar()}}let a = A()
a.foo()// error: 'foo' is inaccessible due to 'private' protection level
a.bar()
fooSolo se puede acceder al método privado dentro del alcance de la class A { ... }definición. Ni siquiera es accesible desde una extensión al tipo (en Swift 3, consulte la segunda nota a continuación para ver los cambios en Swift 4).
Se barpuede acceder al método privado de archivo desde el mismo archivo fuente.
Notas:
La propuesta SE-0159 - Arreglar niveles de acceso privado sugirió volver a la semántica de Swift 2 en Swift 4. Después de una discusión larga y controvertida sobre la lista de correo de evolución rápida, la propuesta fue rechazada .
La propuesta SE-0169 - Mejorar la interacción entre declaraciones y extensiones privadas sugiere hacer que las private
declaraciones dentro de un tipo sean accesibles para extensiones del mismo tipo si la extensión se define en el mismo archivo fuente.
Esta propuesta fue aceptada e implementada en Swift 4.
Si está convirtiendo el código automáticamente de Swift 2 a 3, Xcode se convertirá privateen fileprivate. Sin embargo, si tiene el lujo de hacerlo a mano, a menudo puede beneficiarse de irse privatecomo private... si se compila, todo bien.
Dan Rosenstark
@DanielLarsson: Re sus sugerencias de edición: Ambos comentarios se aplican a la foo()llamada.
Martin R
82
Solo dibujo un diagrama sobre privado , privado de archivos , abierto y público
Espero que pueda ayudarlo rápidamente, para la descripción del texto, consulte la respuesta de Martin R
cuidado, fileprivateno está vinculado a la extensión sino al archivo (escribir una extensión de clase A en otro archivo no permitirá el uso de fileprivatemiembros)
Vince
1
Esto parece incorrecto. Te estás perdiendo el punto clave. Debe diferenciar entre clases que están dentro del mismo módulo y que están en módulos diferentes. Si están en módulos diferentes, entonces publicno le permitirá heredar, por lo tanto, la tercera imagen es incorrecta. Además, siempre puede poner una extensión a cualquier clase si puede verla. Explicar la visibilidad en las extensiones no es una muy buena idea entonces.
Sulthan
De hecho, debería mencionar que mi diagrama funciona solo en el mismo módulo, por lo tanto, la tercera imagen solo quiero que el usuario entienda rápidamente fileprivate solo funciona en el mismo archivo.
Stephen Chen
6
Una regla práctica es que use private para variables, constantes, estructuras internas y clases que se usan solo dentro de la declaración de su clase / estructura. Utiliza fileprivate para cosas que se usan dentro de sus extensiones dentro del mismo archivo que su clase / estructura pero fuera de sus llaves definidas (es decir, su alcance léxico).
classViewController:UIViewController{@IBOutletvar tableView:UITableView!//This is not used outside of class Viewcontroller
privatevar titleText ="Demo"//This gets used in the extension
fileprivatevar list =[String]()overridefunc viewDidLoad(){
navigationItem.title = titleText
}}extensionViewController:UITableViewDataSource{func numberOfSections(in tableView:UITableView)->Int{return list.count
}}
En Swift 4.0, Private ahora es accesible en extensión pero dentro del mismo archivo. Si declara / define la extensión en otro archivo, entonces su variable privada no será accesible para su extensión **
File Private File-private access restringe el uso de una entidad a su propio archivo fuente de definición. Use el acceso privado a archivos para ocultar los detalles de implementación de una funcionalidad específica cuando esos detalles se usan dentro de un archivo completo.
Sintaxis: fileprivate <var type> <variable name> Ejemplo:fileprivate class SomeFilePrivateClass {}
Privado El acceso privado restringe el uso de una entidad a la declaración adjunta y a las extensiones de esa declaración que están en el mismo archivo . Use el acceso privado para ocultar los detalles de implementación de una pieza específica de funcionalidad cuando esos detalles se usan solo dentro de una sola declaración.
Sintaxis: private <var type> <variable name> Ejemplo:private class SomePrivateClass {}
Mire estas imágenes: Archivo: ViewController.swift
Aquí la extensión y el controlador de vista están en el mismo archivo, por lo tanto, la variable privada testPrivateAccessLeveles accesible en extensión
Archivo: TestFile.swift
Aquí la extensión y el controlador de vista están en archivos diferentes, por lo tanto, la variable privada testPrivateAccessLevelno es accesible en extensión.
Aquí la clase ViewController2es una subclase de ViewControllery ambos están en el mismo archivo. Aquí testPrivateAccessLevelno se puede acceder a la variable privada en la Subclase, pero se puede acceder a fileprivate en la subclase.
Aunque la respuesta de @ MartinR y @ StephenChen es perfecta, Swift 4 cambia un poco las cosas.
Privado ahora se considera privado a una clase en la que se declara y también a sus extensiones.
FilePrivate se considera privado en ese archivo, ya sea una clase en la que se define la variable, su extensión o cualquier otra clase definida en ese mismo archivo.
Para mayor claridad, pegue el fragmento de código en Playground
classSum1{let a:Int!let b:Int!privatevar result:Int?fileprivatevar resultt:Int?init(a :Int, b:Int){self.a = a
self.b = b
}func sum(){
result = a + b
print(result as!Int)}}let aObj =Sum1.init(a:10, b:20)
aObj.sum()
aObj.resultt //File Private Accessible as inside same swift file
aObj.result //Private varaible will not be accessible outside its definition except extensions
extensionSum1{func testing(){// Both private and fileprivate accessible in extensions
print(result)
print(resultt)}}//If SUM2 class is created in same file as Sum1 ---
classSum2{func test(){let aSum1=Sum1.init(a:2, b:2)// Only file private accessible
aSum1.resultt
}}
Nota : Fuera del archivo Swift, no se puede acceder a los archivos privados ni a los privados.
filePrivate : el nivel de control de acceso está dentro del archivo.
caso 1 : si creamos una extensión con el mismo archivo de clase e intentamos acceder a la función fileprivate o la propiedad fileprivate en su extensión - acceso permitido caso 2 : si creamos una extensión de clase en un archivo nuevo - Y ahora intentamos acceder a la función fileprivate o fileprivate propiedad - acceso no permitido
privado : el nivel de control de acceso tiene un alcance léxico
caso 1 : Si la propiedad o función se declara como privada en la clase, entonces el alcance es por defecto la clase.
caso 2 : si la instancia privada se declara con el cuerpo de la función, el alcance de la instancia se limita al cuerpo de la función.
Esta es la explicación de swift 4. Para swift 3, la diferencia es el privado. No se puede acceder a swift 3 private por su extensión, solo la clase A puede acceder.
Después de swift 4, fileprivate se vuelve un poco redundante, porque la persona normalmente no definirá la subclase en el mismo archivo. Privado debería ser suficiente para la mayoría de los casos.
private
enfileprivate
. Sin embargo, si tiene el lujo de hacerlo a mano, a menudo puede beneficiarse de irseprivate
comoprivate
... si se compila, todo bien.foo()
llamada.Solo dibujo un diagrama sobre privado , privado de archivos , abierto y público
Espero que pueda ayudarlo rápidamente, para la descripción del texto, consulte la respuesta de Martin R
[Actualizar Swift 4]
fuente
fileprivate
no está vinculado a la extensión sino al archivo (escribir una extensión de clase A en otro archivo no permitirá el uso defileprivate
miembros)public
no le permitirá heredar, por lo tanto, la tercera imagen es incorrecta. Además, siempre puede poner una extensión a cualquier clase si puede verla. Explicar la visibilidad en las extensiones no es una muy buena idea entonces.Una regla práctica es que use private para variables, constantes, estructuras internas y clases que se usan solo dentro de la declaración de su clase / estructura. Utiliza fileprivate para cosas que se usan dentro de sus extensiones dentro del mismo archivo que su clase / estructura pero fuera de sus llaves definidas (es decir, su alcance léxico).
fuente
En Swift 4.0, Private ahora es accesible en extensión pero dentro del mismo archivo. Si declara / define la extensión en otro archivo, entonces su variable privada no será accesible para su extensión **
File Private
File-private access restringe el uso de una entidad a su propio archivo fuente de definición. Use el acceso privado a archivos para ocultar los detalles de implementación de una funcionalidad específica cuando esos detalles se usan dentro de un archivo completo.
Sintaxis:
fileprivate <var type> <variable name>
Ejemplo:
fileprivate class SomeFilePrivateClass {}
Privado
El acceso privado restringe el uso de una entidad a la declaración adjunta y a las extensiones de esa declaración que están en el mismo archivo . Use el acceso privado para ocultar los detalles de implementación de una pieza específica de funcionalidad cuando esos detalles se usan solo dentro de una sola declaración.
Sintaxis:
private <var type> <variable name>
Ejemplo:
private class SomePrivateClass {}
Aquí hay más detalles sobre todos los niveles de acceso: Swift - Niveles de acceso
Mire estas imágenes:
Archivo: ViewController.swift
Aquí la extensión y el controlador de vista están en el mismo archivo, por lo tanto, la variable privada
testPrivateAccessLevel
es accesible en extensiónArchivo: TestFile.swift
Aquí la extensión y el controlador de vista están en archivos diferentes, por lo tanto, la variable privada
testPrivateAccessLevel
no es accesible en extensión.Aquí la clase
ViewController2
es una subclase deViewController
y ambos están en el mismo archivo. AquítestPrivateAccessLevel
no se puede acceder a la variable privada en la Subclase, pero se puede acceder a fileprivate en la subclase.fuente
Aunque la respuesta de @ MartinR y @ StephenChen es perfecta, Swift 4 cambia un poco las cosas.
Privado ahora se considera privado a una clase en la que se declara y también a sus extensiones.
FilePrivate se considera privado en ese archivo, ya sea una clase en la que se define la variable, su extensión o cualquier otra clase definida en ese mismo archivo.
fuente
Actualizado para Swift 5
Privado vs FilePrivate
Para mayor claridad, pegue el fragmento de código en Playground
Nota : Fuera del archivo Swift, no se puede acceder a los archivos privados ni a los privados.
fuente
filePrivate : el nivel de control de acceso está dentro del archivo.
caso 1 : si creamos una extensión con el mismo archivo de clase e intentamos acceder a la función fileprivate o la propiedad fileprivate en su extensión - acceso permitido
caso 2 : si creamos una extensión de clase en un archivo nuevo - Y ahora intentamos acceder a la función fileprivate o fileprivate propiedad - acceso no permitido
privado : el nivel de control de acceso tiene un alcance léxico
caso 1 : Si la propiedad o función se declara como privada en la clase, entonces el alcance es por defecto la clase. caso 2 : si la instancia privada se declara con el cuerpo de la función, el alcance de la instancia se limita al cuerpo de la función.
fuente
En el siguiente ejemplo, las construcciones del lenguaje modificadas por
private
yfileprivate
parecen comportarse de manera idéntica:Esto es de acuerdo con la intuición, supongo. Pero, ¿hay alguna excepción?
Saludos cordiales.
fuente
Esta es la explicación de swift 4. Para swift 3, la diferencia es el privado. No se puede acceder a swift 3 private por su extensión, solo la clase A puede acceder.
Después de swift 4, fileprivate se vuelve un poco redundante, porque la persona normalmente no definirá la subclase en el mismo archivo. Privado debería ser suficiente para la mayoría de los casos.
fuente
Me gusta esto porque es súper simple para ivars.
Intente cambiar fileprivate a privado (y viceversa) y vea qué sucede en la compilación ...
fuente