强制转换为约束协议无法访问默认方法

时间:2017-01-28 05:10:46

标签: swift protocols

我试图访问在协议扩展中定义的默认方法实现,该实现在实现中限制为类。 A'常规'声明工作正常,但是当我尝试转换为协议时,我无法访问协议上的默认定义方法,尽管类型满足where子句。

请考虑这个例子:

class Person {

    var name: String
    init(name: String) {
        self.name = name
    }
}

class Hero: Person {

    var ability: String
    init(name: String, ability: String) {
        self.ability = ability
        super.init(name: name)
    }
}

class Pilot: Person {

    var callSign: String
    init(name: String, callSign: String) {
        self.callSign = callSign
        super.init(name: name)
    }
}

class Programmer: Person {
    var favoriteLanguage: String
    init(name: String, favoriteLanguage: String) {
        self.favoriteLanguage = favoriteLanguage
        super.init(name: name)
    }
}

// define a protocol
protocol PersonPresenter: class { }
// extend it where the conformer is a type of Person
extension PersonPresenter where Self: Person {

    func displayName() {
        print(name.uppercased())
    }
}

// conform subclasses of Person to PersonPresenter
extension Hero: PersonPresenter { }
extension Pilot: PersonPresenter { }
extension Programmer: PersonPresenter { }

let myHero = Hero(name: "Hiro", ability: "Bend time & space")
myHero.displayName() // prints 'HIRO'

let myPilot = Pilot(name: "Pete", callSign: "Maverick")
myPilot.displayName() // prints 'PETE'

let myProgrammer = Programmer(name: "Chris", favoriteLanguage: "Swift")
myProgrammer.displayName() // prints 'CHRS'

let people: [Person] = [myHero,myPilot,myProgrammer]

if let presenter = people[0] as? PersonPresenter {
    presenter.displayName() // Errror, PerseonPresenter is not a subtype of 'Person'
}

我想找到一种在满足where约束的同时强制转换为PersonPresenter的方法,以免被强制尝试转换为每个特定的子类来访问协议扩展的默认实现。或者不必使超类(可以在许多其他地方使用)符合协议。

1 个答案:

答案 0 :(得分:1)

真正的问题是你正在扩展一个空协议。

通过强制转换为Hero,编译器知道它是Person的子类,然后它满足扩展约束。

但是当转换到协议PersonPresenter本身时,编译器不知道是否可以满足约束(作为Person)。

如果您在协议中声明要求,它将起作用:

protocol PersonPresenter: class { 
    func displayName() 
}