协议'BaseListPresenter'只能用作通用约束,因为它具有Self或关联类型要求

时间:2017-05-03 05:48:33

标签: swift generics swift-protocols associated-types

我正在定义一个具有某些功能和变量的协议

protocol BaseListPresenter {
    associatedtype T
    var values: [T] {get}
}

extension BaseListPresenter {

    public func count() -> Int {
        return values.count
    }

    public func valueAtIndex(index: Int) -> T? {
        return values[index]
    }
}

现在,我想在课堂上使用它:

class X: UIViewController {
    var listPresenter: BaseListPresenter? // HERE it gives me error

    // some other functions and variables here
}

上面说的错误:协议'BaseListPresenter'只能用作通用约束,因为它有Self或相关的类型要求

现在,我定义了X的子类:

class Y: X {
    func setPresenter() {
        self.listPresenter = UsersPresenter() // UsersPresenter confirms BaseListPresenter protocol with value's type "User"
    }
    // many more functions below
}

class Z: X {
    func setPresenter() {
        self.listPresenter = RoomsPresenter() // RoomsPresenter confirms BaseListPresenter protocol with value's type "Room"
    }
     // many more functions below
}

我已经通过创建UsersPresenter和RoomsPresenter从(Protocol can only be used as a generic constraint because it has Self or associatedType requirements)获得了解决方案。但是,我想创建BaseListPresenter类型变量,它将在X中采用不同类型的值(UIViewController);一次房间和下一次用户取决于X的子类。

如何解决此问题并按我的意愿使用?

1 个答案:

答案 0 :(得分:0)

问题是,当协议在某处使用时,必须确定协议的关联类型。在您的课程X的实施中,编制者不知道T是什么类型。

我会这样实现:

class X<TPresenter : BaseListPresenter>: UIViewController {
    var listPresenter: TPresenter? // HERE it gives me error

    // some other functions and variables here
}

然后在派生时专门化X

class Y: X<UsersPresenter> {
    func setPresenter() {
        self.listPresenter = UsersPresenter() // UsersPresenter confirms BaseListPresenter protocol with value's type "User"
    }
    // many more functions below
}

class Z: X<RoomsPresenter> {
    func setPresenter() {
        self.listPresenter = RoomsPresenter() // RoomsPresenter confirms BaseListPresenter protocol with value's type "Room"
    }
     // many more functions below
}

这种结构有效。

注意:在UIViewController派生类中使用泛型会让我在一年前遇到麻烦。 Xcode /编译器无法将通用控制器与故事板中的场景链接起来。它不会导致编译错误,但在运行时也没有用 - 花费数小时的诊断时间。