property - swift struct implement protocol




Swift協議要求只能通過使用最終的類來滿足 (2)

如果Student被分類,會發生什麼? 所有者屬性依然為Owner<Student> ,但Student != StudentSubclass

通過使您的Student課程符合Ownee協議,您必須滿足協議的合同。 Ownee協議規定, Owner Ownee有類型約束,使得Owner通用類型是符合OwneeStudent ,在這種情況下)的類型。

如果編譯器允許子類化(即允許你不讓Student最終),那麼StudentSubclass就可能存在。 這樣的子類將繼承Owner<Student>類型的Owner屬性,但Student不是StudentSubclassOwnee協議的合同已被違反,因此,這樣的子類是不允許存在的。

我正在Swift上模擬一個所有者/ ownee計劃:

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

protocol Ownee {
    var owner: Owner<Self> { get }
}

然後我有一對堅持上面模型類型的教授/學生:

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
    }
}

但是,我在Student類的var owner定義中出現以下錯誤:

由於在非參數,非結果類型的位置使用“自我”,所以不能滿足協議“Ownee”要求“所有者”的非最終類(“學生”)

我試圖理解這個錯誤的原因是什麼,為什麼使得Student類最終會解決這個問題,如果有一些解決方法能夠以不同的方式進行建模,而不是使這個類成為最終的。 我已經搜索了這個錯誤,但迄今為止還沒有發現。


錯誤是正確的。 你必須讓你的課程最後,因為沒有Ownee類可以符合你的協議Ownee

考慮這個小類:

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

正如你所看到的,它將不得不實現var owner: Owner<Student>因為他的父,但它應該實現var owner: Owner<FirstGradeStudent>而不是,因為協議包含var owner: Owner<Self> { get }在這種情況下, Self將是第一個FirstGradeStudent

解決方法

1:Ownee定義一個超類,它應該被Owner

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

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

OwneeSuper只是一個解決方法來克服這個問題 ,否則我們只會使用:

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

2.在符合Ownee類中,必須通過定義一個typealias來將associatedtype類型的抽像類型轉換為一個具體類:

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.子類現在可以使用屬性,它將是您定義的類型:

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






swift-protocols