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

时间:2022-06-14 17:08:33

In a class, I defined a private constant, I try to use the constant as a default value of parameter of a function:

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

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

But I get compiler error: Cannot use instance member 'DefaultValue' as a default parameter.

但我得到编译器错误:不能使用实例成员'DefaultValue'作为默认参数。

Then, I also tried declare DefaultValue as private static:

然后,我也尝试将DefaultValue声明为私有静态:

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

But I get new compiler error: Static let 'DefaultValue' is private and cannot be referenced from a default argument value

但是我得到了新的编译器错误:静态让'DefaultValue'是私有的,不能从默认参数值引用

I need to keep DefaultValue private to this class & I would like to assign default value to the parameter of function with a private variable, whether this is achievable in Swift 4?

我需要将DefaultValue保持为此类的私有&我想使用私有变量为函数的参数赋值,是否可以在Swift 4中实现?

3 个解决方案

#1


3  

I don't think that is possible. The default value is inserted at the calling site, and therefore needs to be public, see also Access control in swift 4.

我不认为这是可能的。默认值是在调用站点插入的,因此需要公开,另请参阅swift 4中的访问控制。

A possible workaround would be to make the parameter optional, and substitute nil by the default value locally:

可能的解决方法是使参数可选,并在本地用默认值替换nil:

class Foo {
    private static let DefaultValue = 10

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

#2


1  

A somewhat complicated, but workable, solution, for hiding the default value you want within your class is to use a protocol and a conforming struct whose intimate details are known only by the file declaring Foo:

一个有点复杂但可行的解决方案,用于隐藏你想要的类中的默认值是使用一个协议和一个符合结构的结构,其内部细节只有声明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
    }
}

Callers of doTask are able to pass Int's, while not knowing what the default value provides.

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

#3


0  

How about a top-level variable?

*变量怎么样?

fileprivate let DefaultValue = 10

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

#1


3  

I don't think that is possible. The default value is inserted at the calling site, and therefore needs to be public, see also Access control in swift 4.

我不认为这是可能的。默认值是在调用站点插入的,因此需要公开,另请参阅swift 4中的访问控制。

A possible workaround would be to make the parameter optional, and substitute nil by the default value locally:

可能的解决方法是使参数可选,并在本地用默认值替换nil:

class Foo {
    private static let DefaultValue = 10

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

#2


1  

A somewhat complicated, but workable, solution, for hiding the default value you want within your class is to use a protocol and a conforming struct whose intimate details are known only by the file declaring Foo:

一个有点复杂但可行的解决方案,用于隐藏你想要的类中的默认值是使用一个协议和一个符合结构的结构,其内部细节只有声明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
    }
}

Callers of doTask are able to pass Int's, while not knowing what the default value provides.

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

#3


0  

How about a top-level variable?

*变量怎么样?

fileprivate let DefaultValue = 10

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