Swift 个可选的方法参数,但至少需要填充一个

Swift optional method arguments but at least one needs to be populated

我正在为 swift 中的 class 创建一个带有 2 个参数的方法,它们都是可选的。但是,我至少需要填充其中一个才能使该方法成功运行,哪个都不重要

func someMethod(arg1: Sometype?, arg2: Sometype?)-> Void {
        //I need at least one argument to 
        //be populated to do what i need
}

在 Objective-c 中,如果这两个对象都为 nil,我们可以抛出一个断言。在 Swift 我想知道是否有比断言更好的方法。

您可以改用重载:

// arg1 cannot be nil
func someMethod(arg1: Int, arg2: Int?)-> Void {
    println("arg2 was nil")
    somePrivateMethod(arg1,arg2)
}

// arg2 cannot be nil
func someMethod(arg1: Int?, arg2: Int)-> Void {
    println("arg1 was nil")
    somePrivateMethod(arg1,arg2)
}

// this version is needed to avoid annoying "ambiguous call"
// errors when passing two non-optionals in...
func someMethod(arg1: Int, arg2: Int)-> Void {
    println("neither was nil")
    somePrivateMethod(arg1,arg2)
}

private func somePrivateMethod(arg1: Int?, arg2: Int?)-> Void {
    // private method in which at least arg1 or arg2 will be guaranteed non-nil
}


someMethod(1, nil)  // prints "arg2 was nil"
someMethod(nil, 1)  // prints "arg1 was nil"
someMethod(1, 1)    // prints "neither was nil"

// but if you try this:
someMethod(nil, nil)  // error: cannot find an overload for 'someMethod' 
                      // that accepts an argument list of type '(nil, nil)'

这样做的缺点是调用者被迫展开参数——他们不能在不检查至少其中一个是非零的情况下传递两个可选值。但这是一个功能,而不是错误!因为这意味着调用者实际上不可能意外调用 API "the wrong way" 并生成断言。

当然,这确实会引出一个问题,即您是否真的想要采用不同数量的参数或不同类型的多个重载(请参阅 Rob 的回答),这在您的用例上下文中也值得考虑。

我同意 Airspeed Velocity 的观点,您应该在此处使用重载,但我会以不同的方式进行处理。完全摆脱选项。

func someMethod(#arg1: Sometype)-> Void {}

func someMethod(#arg2: Sometype)-> Void {}

func someMethod(#arg1: Sometype, #arg2: Sometype) -> Void {}

在这一点上,很明显这些是真正不同的方法:

func someMethodWithArg1(arg1: Sometype)-> Void {}

func someMethodWithArg2(arg2: Sometype)-> Void {}

func someMethod(#arg1: Sometype, #arg2: Sometype) -> Void {}

为了使这个具体化,请考虑我们是否正在制作一个 FixedLengthString class,您可以将长度或现有字符串传递给它,或者您可以同时传递两者并重复字符串,直到它填满长度。

您所描述的是:

func makeString(length: Int?, string: String?) -> FixedString

但不仅如此,只需制作方法:

func makeStringWithLength(length: Int) -> FixedString
func makeStringFromString(string: String) -> FixedString
func makeStringByFillingWith(string: String, totalLength: Int) -> FixedString

这样就更清楚了一切是如何运作的,而且你不能错误地调用它。这也是您在 ObjC 中应该做的。