Me gustaría crear una función abstracta en lenguaje rápido. ¿Es posible?
class BaseClass {
func abstractFunction() {
// How do I force this function to be overridden?
}
}
class SubClass : BaseClass {
override func abstractFunction() {
// Override
}
}
Respuestas:
No hay concepto de resumen en Swift (como Objective-C) pero puede hacer esto:
fuente
assert(false, "This method must be overriden by the subclass")
.fatalError("This method must be overridden")
preconditionFailure("Bla bla bla")
en Swift que se ejecutará en versiones de lanzamiento y también elimina la necesidad de una declaración de devolución. EDITAR: Acabo de descubrir que este método básicamente es igualfatalError()
pero es la forma más adecuada (Mejor documentación, presentada en Swift junto conprecondition()
,assert()
yassertionFailure()
, lea aquí )Lo que quieres no es una clase base, sino un protocolo.
Si no proporciona abstractFunction en su clase, es un error.
Si aún necesita la clase base para otro comportamiento, puede hacer esto:
fuente
Porto una buena cantidad de código desde una plataforma que admite clases base abstractas a Swift y me encuentro mucho con esto. Si lo que realmente desea es la funcionalidad de una clase base abstracta, eso significa que esta clase sirve tanto como una implementación de la funcionalidad de clase basada compartida (de lo contrario, solo sería una interfaz / protocolo) Y define métodos que deben implementarse mediante clases derivadas
Para hacer eso en Swift, necesitará un protocolo y una clase base.
Tenga en cuenta que la clase base implementa los métodos compartidos, pero no implementa el protocolo (ya que no implementa todos los métodos).
Luego en la clase derivada:
La clase derivada hereda sharedFunction de la clase base, lo que le ayuda a satisfacer esa parte del protocolo, y el protocolo aún requiere que la clase derivada implemente abstractFunction.
El único inconveniente real de este método es que, dado que la clase base no implementa el protocolo, si tiene un método de clase base que necesita acceso a una propiedad / método de protocolo, tendrá que anularlo en la clase derivada, y desde allí llamar la clase base (a través de super) pasando
self
para que la clase base tenga una instancia del protocolo con el que hacer su trabajo.Por ejemplo, digamos que sharedFunction necesitaba llamar a abstractFunction. El protocolo permanecería igual y las clases ahora se verían así:
Ahora, la función compartida de la clase derivada satisface esa parte del protocolo, pero la clase derivada aún puede compartir la lógica de la clase base de una manera razonablemente sencilla.
fuente
Esta parece ser la forma "oficial" de cómo Apple maneja métodos abstractos en UIKit. Eche un vistazo
1. Ponga el método abstracto en un protocolo 2. Escribe tu clase base 3. Escriba la subclase (s). Aquí está, cómo usar todo esoUITableViewController
y la forma en que funcionaUITableViewDelegate
. Una de las primeras cosas que hacer, es añadir una línea:delegate = self
. Bueno, ese es exactamente el truco.Consulte con Playground para ver la salida.
Algunas observaciones
UITableViewController
implementaUITableViewDelegate
pero aún necesita ser registros como delegado estableciendo explícitamente ladelegate
propiedad.fuente
getComments
método en el delegado principal. Hay un puñado de tipos de comentarios, y quiero los relevantes para cada objeto. Entonces, quiero que las subclases no se compilen cuando lo hagodelegate.getComments()
si no anulo ese método. El VC solo sabe que tiene unParentDelegate
objeto llamadodelegate
, oBaseClassX
en su ejemplo, peroBaseClassX
no tiene el método abstracto. Necesitaría el VC para saber específicamente que está usando elSubclassedDelegate
.Una forma de hacerlo es usar un cierre opcional definido en la clase base, y los niños pueden elegir implementarlo o no.
fuente
Bueno, sé que llego tarde al juego y que podría estar aprovechando los cambios que han sucedido. Lo siento por eso.
En cualquier caso, me gustaría contribuir con mi respuesta, porque me encanta hacer las pruebas y las soluciones con
fatalError()
, AFAIK, no son verificables y las que tienen excepciones son mucho más difíciles de probar.Sugeriría utilizar un enfoque más rápido . Su objetivo es definir una abstracción que tenga algunos detalles comunes, pero que no esté completamente definida, es decir, el método o métodos abstractos. Utilice un protocolo que defina todos los métodos esperados en la abstracción, tanto los definidos como los que no. Luego, cree una extensión de protocolo que implemente los métodos que se definen en su caso. Finalmente, cualquier clase derivada debe implementar el protocolo, lo que significa todos los métodos, pero los que forman parte de la extensión del protocolo ya tienen su implementación.
Extendiendo su ejemplo con una función concreta:
Tenga en cuenta que al hacer esto, el compilador vuelve a ser su amigo. Si el método no se "anula", obtendrá un error en el momento de la compilación, en lugar de los que obtendrá
fatalError()
o las excepciones que sucederán en el tiempo de ejecución.fuente
Entiendo lo que estás haciendo ahora, creo que sería mejor usar un protocolo
Luego, simplemente se ajusta al protocolo:
Si su clase también es una subclase, los protocolos siguen la Superclase:
fuente
Uso de
assert
palabras clave para imponer métodos abstractos:Sin embargo, como Steve Waddicor mencionó, probablemente quieras un
protocol
lugar.fuente
Entiendo la pregunta y estaba buscando la misma solución. Los protocolos no son lo mismo que los métodos abstractos.
En un protocolo, debe especificar que su clase se ajusta a dicho protocolo, un método abstracto significa que debe anular dicho método.
En otras palabras, los protocolos son una especie de opciones, debe especificar la clase base y el protocolo; si no especifica el protocolo, no tiene que anular dichos métodos.
Un método abstracto significa que desea una clase base pero necesita implementar su propio método o dos, que no es lo mismo.
Necesito el mismo comportamiento, es por eso que estaba buscando una solución. Supongo que a Swift le falta esa característica.
fuente
Hay otra alternativa a este problema, aunque todavía hay un inconveniente en comparación con la propuesta de @ jaumard; Requiere una declaración de devolución. Aunque pierdo el punto de requerirlo, porque consiste en lanzar directamente una excepción:
Y entonces:
Lo que venga después de eso es inalcanzable, así que no veo por qué forzar el regreso.
fuente
AbstractMethodException().raise()
?No sé si será útil, pero tuve un problema similar con el método abstracto al intentar construir el juego SpritKit. Lo que quería es una clase abstracta de Animal que tenga métodos como move (), run (), etc., pero los niños de la clase deberían proporcionar nombres de sprites (y otras funciones). Así que terminé haciendo algo como esto (probado para Swift 2):
fuente