难以将默认值分配给函数的参数

时间:2018-09-18 18:58:01

标签: 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) {
    ...
  }
}

但是我收到编译器错误:Cannot use instance member 'DefaultValue' as a default parameter

然后,我还尝试将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' is private and cannot be referenced from a default argument value

我需要将DefaultValue 私有保留给此类,并且我想使用私有变量将默认值分配给函数的参数,无论这在Swift 4中是否可以实现? / p>

4 个答案:

答案 0 :(得分:6)

我认为不可能。默认值插入在呼叫站点,因此需要公开,另请参见 Access control in swift 4

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

class Foo {
    private static let DefaultValue = 10

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

答案 1 :(得分:1)

在类中隐藏您想要的默认值的一种稍微复杂但可行的解决方案是使用协议和一致的结构,其私密细节仅通过声明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,而不必知道默认值提供了什么。

答案 2 :(得分:0)

顶级变量如何?

fileprivate let DefaultValue = 10

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

答案 3 :(得分:0)

如果使用 nil 可能不是很明显,并且任务很小或很容易放在私有函数中,只需添加另一个签名即可。

您甚至可以将其更改为 doTaskWithDefaultAmount(),具体取决于用户了解此默认值的重要性。

class Foo {
    public func doTask() {
        calculateStuff(from: self.defaultValue)
    }
   
    public func doTask(amount: Int) {
        calculateStuff(from: amount)
    }
}