Swift协议和多态

Odr*_*kir 5 ios swift

我一直试图让这段代码起作用

protocol Shootable
{
    func shoot ()
}

protocol Shooter
{
    var weapon:Shootable { get set }
}

class Gun:Shootable
{
    func shoot() {

    }

    func someOtherMethod()
    {

    }
}

class Player:Shooter
{
    var weapon:Gun

    init ()
    {
        weapon = Gun()
        weapon.someOtherMethod()
    }
}
Run Code Online (Sandbox Code Playgroud)

但是编译器告诉我Player不符合Shooter协议.我认为这是因为玩家武器变量是Gun类型,而不是Shootable,即使Gun实现了Shootable.

但后来我改变了这个,现在它起作用了:

protocol Shooter
{
    typealias Weapon:Shootable
    var weapon:Weapon { get set }
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么.我认为typealiases只是给了一个类型的另一个名字,我不知道这种能力......

任何人都可以对此有所了解吗?

Mat*_*mbo 0

据我所知,声明typealias内部protocol类似于声明泛型类型。在声明中使用协议类型即声明您将仅将其用于协议声明的内容。

如果您编写以下内容,您的第一个示例将起作用:

class Player:Shooter
{
    var weapon:Shootable

    init ()
    {
        weapon = Gun()
        /* weapon.someOtherMethod()
        Can't use it 'cause weapon is strictly a Shootable, thus it is not meant to have any other methods than shoot()
        */
    }
}
Run Code Online (Sandbox Code Playgroud)

您的第二个示例有效,因为您在协议内声明了泛型类型并要求它是符合Shootable. 您的修改利用了类型推断,因此第二个示例的以下重写可能会更清楚:

class Player:Shooter
{
    typealias Weapon = Gun
    var weapon:Weapon

    init ()
    {
        weapon = Gun()
        weapon.someOtherMethod()
    }
}
Run Code Online (Sandbox Code Playgroud)

这里我明确声明通用协议类型别名WeaponGun(并且因为它符合Shootable所有就可以了)。在您的示例中,这是由编译器隐式推断的,因为没有歧义。