2015-03-19 116 views
4

我一直试图让这个代码工作斯威夫特协议和多态性

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

但是,编译器告诉我,球员不符合射手协议。我认为这是因为玩家武器变种是Gun类型的,不可射击,即使Gun实现Shootable。

但后来我改变了这一点,现在,它的工作原理:

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

而且我不知道为什么。我以为typealiases只是给一个类型另一个名字,我并不知道这种能力...

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

+0

如果您在播放器类中声明武器为可在协议中进行拍摄,并将init中包含someOtherMethod()的行更改为(武器为枪).someOtherMethod(),它将起作用。虽然,我没有解释为什么它可以用于typealias。 – 2015-03-19 10:02:45

+0

我知道,但我不想这样做,使其工作。 – Odrakir 2015-03-19 10:16:49

回答

0

AFAIK typealias里面的声明是类似于声明通用类型。使用协议在声明中键入声明您将仅用于协议声明的内容。

你的第一个例子中的情况下工作,你写:

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() 
     */ 
    } 
} 

你的第二个例子工程,因为你声明通用类型的协议内,并要求它符合Shootable一个类型。您修改利用类型推断的,因此可以更清楚你的第二个例子如下改写:

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

    init() 
    { 
     weapon = Gun() 
     weapon.someOtherMethod() 
    } 
} 

在这里,我明确地声明,通用协议类型别名WeaponGun(并且由于它符合Shootable一切都好)。在你的例子中,这是由编译器隐式推断的,因为没有歧义。

+0

也许更简单的方法来看看为什么你的第一个例子不起作用正在考虑声明一个'Shootable'的数组:'var sh = [Shootable]()'。你可以合理地使用这个数组的元素来调用'shoot()'。因此,你可以给该数组添加一个'Gun',但是你不能在它的_scope_中使用它作为一个不同的形式的Shootable。 – 2015-03-19 09:29:15

+0

我明白为什么第一个例子不起作用。不过,如果编译器足够聪明以知道Gun是可拍摄的,我认为它可以工作。实际上类似的东西肯定会对Objective-C起作用。关于第二个例子,我认为我混合了typealias Weapon:可以用typealias Weapon = Shootable来启动。前者的工作类似于受限制的泛型,后者只是重命名类型。 – Odrakir 2015-03-19 09:55:21

+0

由于没有人使用Swift 5年的经验,并且它仍在进化中,请将我的观点作为_第一印象_。使用Objective-C非常普遍的是使用_protocols_来扩展一个类。在Swift中,我们有'extension',因此我认为'protocol'将会采用完全不同的_use case_。最后,我怀疑'protocol'在Obj-C和Swift上会有很不相同的含义。您的_type design_将在Swift中更加相关,因为它可以被视为严格键入_ – 2015-03-19 15:32:50