带有`default`参数值的Swift协议

在一个非常常见的情况下,您有一个 ,其中包含带有默认参数值的方法,并且您要对其进行测试。

  Baz类{ 
      func foo(bar:BarType,camp:CampType = CampType())->字符串{ 
          返回“世界” 
      }  
  } 

首先编写协议,以便可以为类实现模拟,如下所示:

  协议BazProtocol { 
      func foo(bar:BarType,camp:CampType)->字符串 
  } 

模拟

  struct BazMock:BazProtocol { 
      func foo(bar:BarType,camp:CampType)->字符串{ 
          返回“” 
      } 
  } 

您希望模拟共享默认值,因此首先要在协议定义中设置默认值,最后得到类似这样的内容。

  协议BazProtocol { 
      func foo(bar:BarType,camp:CampType =“ Hello”)->字符串 
  } 

但是您得到以下错误:

default argument not permitted in a protocol method

有一种方法可以解决该限制。

扩展程序可以解救!

我们不会在Baz或BazMock上定义默认参数,但将使用协议扩展名 ,这是将定义默认值的唯一位置。 这样,同一协议的两个实现都具有相同的默认值。

  扩展名BazProtocol { 
      func foo( 
          bar:BarType, 
          camp:CampType = CampType())->字符串{ 
          返回foo(bar:bar,camp:camp) 
      } 
  } 

这里发生的是,我们在扩展程序内部调用了协议定义的函数foo,该函数在运行时将使用扩展程序的默认值从具体类型中调用正确的方法。

*重要说明*因为 如果您在对象中使用 协议 BazProtocol ,扩展名中已经有默认的实现,并且 忘记 实现函数foo编译器不会抱怨,但是扩展功能foo将递归调用其自身,直到您的代码使用BAD_ACCESS崩溃为止。

如此简单,我们就有带有默认值的协议方法定义。

感谢Kostas Kremizas和Pavlos-Petros Tournaris的反馈。