代码之家  ›  专栏  ›  技术社区  ›  Leem

将默认值赋给函数的参数有困难

  •  7
  • Leem  · 技术社区  · 6 年前

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

    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

    我需要保持 默认值 私有的 对于此类,我想为带有私有变量的函数的参数分配默认值,这是否可以在swift 4中实现?

    3 回复  |  直到 6 年前
        1
  •  6
  •   Martin R    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
            // ...
        }
    }
    
        2
  •  1
  •   Cristik    6 年前

    在类中隐藏所需默认值的一个有点复杂但可行的解决方案是使用协议和一致结构,其详细信息仅由声明 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 而不知道默认值提供了什么。

        3
  •  0
  •   Mike Henderson    6 年前

    顶级变量怎么样?

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