A Swift protocol requirement that can only be satisfied by using a final class

The Error is correct. You have to make your class final, since no subclasses could conform your protocol Ownee.

Consider this subclass:

class FirstGradeStudent: Student {
   // Student contains following variable:
   // var owner: Owner<Student> {
   //     return professor
   //  }
}

As you can see, it would have to implement var owner: Owner<Student> because of his parent, but it should be implementing var owner: Owner<FirstGradeStudent> instead, because the protocol contains var owner: Owner<Self> { get } and in this case Self would be FirstGradeStudent.

Workaround

1: Define a superclass to Ownee, it should be used by Owner:

class Owner<T: OwneeSuper> {
    // ...
}

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

OwneeSuper is just a workaround to overcome this problem, otherwise we would just be using:

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

2. In classes that conform to Ownee, you must turn the abstract type of the associatedtype into a concrete class by defining a 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. Subclasses can now make use of the property, which will be of your defined type:

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

Leave a Comment