type tuple generic functions extension swift oop generics swift-protocols

tuple - Un requisito de protocolo Swift que solo se puede satisfacer utilizando una clase final



tuple swift (3)

¿Qué sucede si el Student está subclasificado? La propiedad del propietario sigue siendo Owner<Student> , pero Student != StudentSubclass .

Al hacer que su clase de Student ajuste al protocolo de Ownee , debe cumplir con el contrato del protocolo. El protocolo de Ownee establece que el Owner tiene una restricción de tipo, de modo que el tipo genérico de Owner es del tipo que se ajusta a Ownee ( Student , en este caso).

Si el compilador permitiera la creación de subclases (es decir, permitiéndole no hacer que el Student final), entonces sería posible que exista una StudentSubclass de StudentSubclass de StudentSubclass . Dicha subclase heredará la propiedad Owner , de tipo Owner<Student> , pero Student no es lo mismo que StudentSubclass . El Ownee protocolo de Ownee ha sido violado, por lo tanto, no se puede permitir que exista dicha subclase.

Estoy modelando un esquema propietario / propietario en Swift:

class Owner<T: Ownee> { // ... } protocol Ownee { var owner: Owner<Self> { get } }

Luego tengo un par de clases profesor / alumno que se adhieren a los tipos de modelos anteriores:

class Professor: Owner<Student> { // ... } class Student: Ownee { let professor: Professor var owner: Owner<Student> { // error here (see below) return professor } init(professor: Professor) { self.professor = professor } }

Sin embargo, aparece el siguiente error en la definición de var owner de var owner en la clase de Student :

El requisito ''propietario'' del protocolo ''Ownee'' no puede ser satisfecho por una clase no final (''Estudiante'') porque usa ''Auto'' en una posición sin parámetro y sin resultado

Intento entender cuál es la causa de este error, por qué hacer que la clase Student final lo arregle, y si hay alguna solución para poder modelar esto de manera diferente, sin hacer que esta clase sea definitiva. Busqué en Google ese error, pero hasta ahora no he encontrado demasiado.


El error es correcto Tienes que hacer que tu clase sea definitiva, ya que ninguna subclase podría conformar tu protocolo Ownee .

Considera esta subclase:

class FirstGradeStudent: Student { // inherited from parent // var owner: Owner<Student> { // return professor // } }

Como puede ver, tendría que implementar el var owner: Owner<Student> debido a su padre, pero debería implementar el var owner: Owner<FirstGradeStudent> , porque el protocolo contiene var owner: Owner<Self> { get } y en este caso, Self sería FirstGradeStudent .

Solución

1: defina una superclase para Ownee , debe ser utilizada por el Owner :

class Owner<T: OwneeSuper> { // ... } protocol OwneeSuper {} protocol Ownee: OwneeSuper { associatedtype T: OwneeSuper var owner: Owner<T> { get } }

OwneeSuper es solo una solución para superar este problema , de lo contrario solo estaríamos usando:

protocol Ownee { associatedtype T: Ownee var owner: Owner<T> { get } }

2. En las clases que se ajustan a Ownee , debe convertir el tipo abstracto del tipo associatedtype en una clase concreta definiendo una typealias :

class Student: Ownee { typealias T = Student // <<-- define the property to be Owner<Student> let professor: Professor var owner: Owner<T> { return professor } init(professor: Professor) { self.professor = professor } }

3. Las subclases ahora pueden hacer uso de la propiedad, que será de su tipo definido:

class FirstGradeStudent: Student { func checkOwnerType() { if self.owner is Owner<Student> { //warning: ''is'' test is always true print("yeah!") } } }


La siguiente sintaxis debe ser compatible con lo que busca:

protocol Ownee { associatedtype Owned = Self where Owned:Ownee var owner: Owner<Owned> { get } }

(probado usando Swift 4 - Beta 1)