Swift 强制转换到受约束协议无法访问默认方法

Swift 强制转换到受约束协议无法访问默认方法,swift,protocols,Swift,Protocols,我试图访问在协议扩展中定义的默认方法实现,该协议扩展在实现中受类的约束。“常规”声明可以正常工作,但是当我尝试强制转换到协议时,我无法访问协议上的默认定义方法,尽管类型满足where子句 请考虑这个例子: class Person { var name: String init(name: String) { self.name = name } } class Hero: Person { var ability: String i

我试图访问在协议扩展中定义的默认方法实现,该协议扩展在实现中受类的约束。“常规”声明可以正常工作,但是当我尝试强制转换到协议时,我无法访问协议上的默认定义方法,尽管类型满足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,这样就不会被迫尝试并强制转换到每个特定的子类来访问协议扩展的默认实现。或者不必使超类(可能在许多其他地方使用)符合协议

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

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

但是当转换到ProtocolPersonPresenter本身时,编译器不知道约束(作为一个人)是否可以得到满足

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

protocol PersonPresenter: class { 
    func displayName() 
}