Generics 怎么说;“同一类”;迅速地

Generics 怎么说;“同一类”;迅速地,generics,swift,Generics,Swift,如果Swift泛型类型约束是协议名称,我可以要求约束到该协议的两个类型是相同的类型。例如: protocol Flier {} struct Bird : Flier {} struct Insect: Flier {} func flockTwoTogether<T:Flier>(f1:T, f2:T) {} 问题是,我可以使用WellBehavedDog和NoisedDog一起调用Walktwow。这就是我想要阻止的 这里有两个问题: 有没有一种方法可以说不能用WellBeh

如果Swift泛型类型约束是协议名称,我可以要求约束到该协议的两个类型是相同的类型。例如:

protocol Flier {}
struct Bird : Flier {}
struct Insect: Flier {}
func flockTwoTogether<T:Flier>(f1:T, f2:T) {}
问题是,我可以使用WellBehavedDog和NoisedDog一起调用
Walktwow
。这就是我想要阻止的

这里有两个问题:

  • 有没有一种方法可以说不能用WellBehavedDog和NoisedDog调用
    一起行走

  • 这是虫子吗?我这样问是因为如果我不能用泛型来表达这一点,很难理解为什么泛型约束作为类名是有用的,因为我们可以用普通函数得到相同的结果

    • 从本质上说,这不是一个答案,但可能还有更多的数据。。。问题是当你打电话时:

      walkTwoTogether(NoisyDog(), WellBehavedDog())
      
      Swift可以把这两个实例都当作
      Dog
      (又称为upcast)的实例来处理——我们需要它,这样我们就可以用
      A
      的子类调用类
      A
      的方法。(我知道你知道这一点。)

      Swift不向上转换协议,因此唯一的方法是为超类不符合的子类指定协议:

      protocol Walkable {}
      extension NoisyDog : Walkable {}
      extension WellBehavedDog: Walkable {}
      func walkTwoTogether<T: Dog where T: Walkable>(d1:T, d2:T) { }
      
      walkTwoTogether(NoisyDog(), WellBehavedDog())
      // error: type 'Dog' does not conform to protocol 'Walkable'
      
      protocolwalkable{}
      扩展名noisedog:Walkable{}
      扩展井行波道:可行走{}
      func walktowethowe(d1:T,d2:T){}
      一起演练(noisedog(),welleHavedDog())
      //错误:类型“Dog”不符合协议“Walkable”
      

      错误消息明确显示发生了什么-调用此版本的
      walkToTogether
      的唯一方法是将子类实例上溯到
      Dog
      ,但是
      Dog
      不符合
      Walkable

      我认为这应该被视为一个bug,因为
      inout
      参数改变了类型要求:

      func walkTwoTogether<T:Dog>(inout d1:T, d2:T) {
      
      func一起演练(inout d1:T,d2:T){
      

      现在,它具有预期的行为,您只能传递相同类型的两个值。(在Swift 1.2和Swift 2 beta 5中测试)

      对我来说,这似乎是预期的行为?您已将可选项约束为Dog类型。您的两个子类都符合该类型,并且声明中没有任何内容约束它们。如果有办法实现您的要求,我希望它需要一个
      where
      子句,如
      ,但这也会引发一个错误。@cmyr Yes,当然,我试过了。这就是为什么我问我所做的不是如何做,是否有可能做到。:)如果
      Dog
      是一个协议,这一切都会起作用。非协议类型不能强制执行通用约束。(某种类型擦除)@马特这就是为什么我很好奇为什么T:SomeClass是允许的。文档明确地说你可以这样做,但我不明白为什么它有用。我的意思是,如果它不强制执行任何东西,那是为什么?如果我想让任何两个狗类子类可以一起行走,我可以使用一个非泛型函数。看起来你在自言自语,马特(T).:)幸运的是,我没有像我最初向自己提出的那样提出这个问题,这是为了区分Dog和noisedog!不允许使用子类!是和否。这是合法的:
      var d:Dog=wellehaveddog();walktoweach(&d,noisedog())
      在任何情况下,如果有缺陷,我想我们最多只能说是不一致;不清楚哪一个是对的。@matt Your是对的,可能是其中一个。在您的情况下,您必须用
      inout
      标记两个参数。有趣的是,如果不使用泛型约束,它的行为几乎相同。我比e更困惑没错!但是你的数据真的很有趣,这是毫无疑问的。
      func walkTwoTogether<T:Dog>(inout d1:T, d2:T) {