Swift 为函数的参数指定默认值的困难

Swift 为函数的参数指定默认值的困难,swift,swift4,Swift,Swift4,在一个类中,我定义了一个私有常量,我尝试使用该常量作为函数参数的默认值: class Foo { // instance variable private let DefaultValue = 10 // Compiler error: Cannot use instance member 'DefaultValue' as a default parameter public func doTask(amount: Int = DefaultValue) { ...

在一个类中,我定义了一个私有常量,我尝试使用该常量作为函数参数的默认值:

class Foo {
  // instance variable
  private let DefaultValue = 10

  // Compiler error: Cannot use instance member 'DefaultValue' as a default parameter
  public func doTask(amount: Int = DefaultValue) {
    ...
  }
}
但我得到了编译器错误:
无法将实例成员“DefaultValue”用作默认参数

然后,我还尝试将
DefaultValue
声明为
private static

class Foo {
      // static variable
      private static let DefaultValue = 10

      // Compiler error: Static let 'DefaultValue' is private and cannot be referenced from a default argument value
      public func doTask(amount: Int = DefaultValue) {
        ...
      }
    }
但我得到了新的编译器错误:
Static let'DefaultValue'是私有的,不能从默认参数值引用


我需要将
DefaultValue
private保留给这个类&我想用一个私有变量为函数的参数指定默认值,这在Swift 4中是否可以实现?

我认为这是不可能的。默认值插入到调用站点,因此需要是公共的,请参见

一种可能的解决方法是将参数设置为可选, 并用本地默认值替换
nil

class Foo {
    private static let DefaultValue = 10

    public func doTask(amount: Int? = nil) {
        let amount = amount ?? Foo.DefaultValue
        // ...
    }
}

在类中隐藏默认值的一个有点复杂但可行的解决方案是使用协议和一致性结构,其详细信息只有声明
Foo
的文件才能知道:

// enabling custom stuff
public protocol IntLike {
    var intValue: Int { get }
}

// allowing to pass Int's
extension Int: IntLike {
    public var intValue: Int { return self }
}

public class Foo {
    // the placeholder
    public struct FooIntLike: IntLike {
        // what we really want to hide
        fileprivate let realInt = 10

        public init() { }

        public var intValue: Int = Int.max // or 0, or whatever
    }

    public func doTask(amount: IntLike = FooIntLike()) {
        // default value will expand to a non-nil value for `realInt`
        let amount = (amount as? FooIntLike)?.realInt ?? amount.intValue
        // do your stuff with the amount
    }
}

doTask
的调用者能够传递
Int
,而不知道默认值提供了什么。

顶级变量如何

fileprivate let DefaultValue = 10

class Foo {
    public func doTask(amount: Int = DefaultValue) {
        ...
    }
}

为什么
DefaultValue
需要保持私有?在Swift 5中,默认参数表达式现在显示在模块生成的接口中,因此默认参数只能引用
public
事物(比较)@Hamish:Duplicate?@MartinR-Hmm,您的答案更直接地回答了OP的问题,所以我建议保持它的打开状态。
Foo.FooIntLike()同样?@MartinR
realInt
fileprivate
,这使得无法访问源代码的调用方(例如框架客户端)无法使用它。如果调用方可以访问源代码,那么问题中的问题就没有解决方案了。你是对的。但是
print(Foo.FooIntLike())
打印
FooIntLike(realInt:10,intValue:9223372036854775807)
,因此您可能需要将描述方法重写为well@MartinR有效的一点,但是想知道如果从外部上下文调用,描述是否相同,我怀疑Swift会允许如此容易地泄露私人细节。我只使用单独的源文件,而不是单独的框架进行了测试。是的,这种情况可能会有所不同。请注意,如果
class Foo
public
,则不会编译。