¿Hay alguna manera de crear una clase abstracta en el lenguaje Swift o es una limitación al igual que Objective-C? Me gustaría crear una clase abstracta comparable a lo que Java define como una clase abstracta.
140
¿Hay alguna manera de crear una clase abstracta en el lenguaje Swift o es una limitación al igual que Objective-C? Me gustaría crear una clase abstracta comparable a lo que Java define como una clase abstracta.
Respuestas:
No hay clases abstractas en Swift (al igual que Objective-C). Su mejor opción será utilizar un protocolo , que es como una interfaz Java.
Con Swift 2.0, puede agregar implementaciones de métodos e implementaciones de propiedades calculadas utilizando extensiones de protocolo. Sus únicas restricciones son que no puede proporcionar variables miembro o constantes y no hay despacho dinámico .
Un ejemplo de esta técnica sería:
Tenga en cuenta que esto proporciona características de "clase abstracta" incluso para estructuras, pero las clases también pueden implementar el mismo protocolo.
Observe también que cada clase o estructura que implemente el protocolo del Empleado deberá declarar nuevamente la propiedad del Salario anual.
Lo más importante, tenga en cuenta que no hay despacho dinámico . Cuando
logSalary
se llama en la instancia que se almacena comoSoftwareEngineer
, llama a la versión anulada del método. Cuando se invocalogSalary
en la instancia después de que se ha convertido en unEmployee
, llama a la implementación original (no se envía dinámicamente a la versión anulada, aunque la instancia es realmente unSoftware Engineer
.Para obtener más información, consulte el excelente video de WWDC sobre esa característica: Crear mejores aplicaciones con tipos de valor en Swift
fuente
protocol Animal { var property : Int { get set } }
. También puede omitir el conjunto si no desea que la propiedad tenga un setterfunc logSalary()
a la declaración de protocolo de empleado, el ejemplo se imprimeoverridden
para ambas llamadas alogSalary()
. Esto está en Swift 3.1. Así obtienes los beneficios del polimorfismo. Se llama al método correcto en ambos casos.Tenga en cuenta que esta respuesta está dirigida a Swift 2.0 y superior
Puede lograr el mismo comportamiento con protocolos y extensiones de protocolo.
Primero, escribe un protocolo que actúa como una interfaz para todos los métodos que deben implementarse en todos los tipos que se ajustan a él.
Luego, puede agregar un comportamiento predeterminado a todos los tipos que lo conforman
Ahora puede crear nuevos tipos mediante la implementación
Drivable
.Entonces básicamente obtienes:
Drivable
implementenspeed
Drivable
(accelerate
)Drivable
está garantizado para no ser instanciado ya que es solo un protocoloEste modelo en realidad se comporta mucho más como rasgos, lo que significa que puede ajustarse a múltiples protocolos y asumir implementaciones predeterminadas de cualquiera de ellos, mientras que con una superclase abstracta está limitado a una jerarquía de clases simple.
fuente
UICollectionViewDatasource
,. Me gustaría eliminar todo el repetitivo y encapsularlo en un protocolo / extensión separado y luego reutilizarlo en varias clases. De hecho, el patrón de plantilla sería perfecto aquí, pero ...Creo que esto es lo más cercano a Java
abstract
o C #abstract
:Tenga en cuenta que, para que los
private
modificadores funcionen, debe definir esta clase en un archivo Swift separado.EDITAR: Aún así, este código no permite declarar un método abstracto y, por lo tanto, forzar su implementación.
fuente
La forma más simple es utilizar una llamada al
fatalError("Not Implemented")
método abstracto (no variable) en la extensión del protocolo.fuente
(MyConcreteClass() as MyInterface).myMethod()
pero lo hace! La clave está incluidamyMethod
en la declaración del protocolo; de lo contrario, la llamada se bloquea.Después de luchar durante varias semanas, finalmente me di cuenta de cómo traducir una clase abstracta de Java / PHP a Swift:
Sin embargo, creo que Apple no implementó clases abstractas porque generalmente usa el patrón delegado + protocolo en su lugar. Por ejemplo, el mismo patrón anterior se haría mejor así:
Necesitaba este tipo de patrón porque quería comúnizar algunos métodos en UITableViewController como viewWillAppear, etc. ¿Fue útil?
fuente
Hay una manera de simular clases abstractas usando Protocolos. Esto es un ejemplo:
fuente
Una forma más de cómo puede implementar la clase abstracta es bloquear el inicializador. Lo he hecho de esta manera:
fuente
Estaba tratando de hacer una
Weather
clase abstracta, pero el uso de protocolos no era ideal ya que tenía que escribir los mismosinit
métodos una y otra vez. Extender el protocolo y escribir uninit
método tenía sus problemas, especialmente porque estaba usando laNSObject
conformidad conNSCoding
.Entonces se me ocurrió esto por la
NSCoding
conformidad:En cuanto a
init
:fuente
Mueva todas las referencias a propiedades abstractas y métodos de la clase Base a la implementación de extensión de protocolo, donde Auto restricción a la clase Base. Obtendrá acceso a todos los métodos y propiedades de la clase Base. Además, el compilador verifica la implementación de métodos abstractos y propiedades en el protocolo para clases derivadas
fuente
Con la limitación de ningún despacho dinámico, puede hacer algo como esto:
fuente