Ответ 1
Обновление для Swift 2.0. Теперь функции ведут себя одинаково с методами и для обоих по умолчанию:
- первый параметр не имеет внешнего имени; и
- другие параметры имеют внешнее имя, идентичное внутреннему имени.
Кроме этого, правила ниже все еще применяются, за исключением того, что сокращенный синтаксис #
теперь отсутствует.
Здесь более общий ответ: функции ведут себя по-разному, если они определены как истинные функции вне класса, и когда они определены как методы. Более того, методы init имеют специальное правило.
Функции
Предположим, вы определили это:
func multiply1(f1: Double, f2: Double) -> Double {
return f1 * f2
}
Имена параметров здесь только локальные для функции и не могут использоваться при вызове функции:
multiply1(10.0, 10.0)
Если вы хотите принудительно использовать именованные параметры при вызове функции, вы можете. Префикс объявления каждого параметра с его внешним именем. Здесь внешнее имя f1
равно f1param
, а для f2
мы используем сокращенное обозначение, где мы его префикс #
, чтобы указать, что локальное имя также должно использоваться как внешнее имя:
func multiply2(f1param f1: Double, #f2: Double) -> Double {
return f1 * f2
}
Затем должны использоваться именованные параметры:
multiply2(f1param: 10.0, f2: 10.0)
Методы
Для методов разные. По умолчанию все, кроме первого параметра, называются, как вы обнаружили. Предположим, что мы имеем это, и рассмотрим метод multiply1
:
class Calc {
func multiply1(f1: Double, f2: Double) -> Double {
return f1 * f2
}
func multiply2(f1param f1: Double, f2: Double) -> Double {
return f1 * f2
}
func multiply3(f1: Double, _ f2: Double) -> Double {
return f1 * f2
}
}
Затем вы должны использовать имя второго (и следующих, если есть) параметров:
let calc = Calc()
calc.multiply1(1.0, f2: 10.0)
Вы можете принудительно использовать именованный параметр для первого аргумента, указав для него внешнее имя, например, для функций (или префикс его локального имени #
, если вы хотите использовать то же самое внешнее имя, что и его локальное имя), Затем вы должны использовать его:
calc.multiply2(f1param: 10.0, f2: 10.0)
Наконец, вы можете объявить внешнее имя _
для других следующих аргументов, указав, что вы хотите вызвать свой метод без использования именованных параметров, например:
calc.multiply3(10.0, 10.0)
Замечание по совместимости: Если вы префикс class Calc
с аннотацией @objc
, то вы можете использовать его из кода Objective-C и он эквивалентен этому объявлению (смотрите имена параметров)
@interface Calc
- (double)multiply1:(double)f1 f2:(double)f2;
- (double)multiply2WithF1param:(double)f1 f2:(double)f2;
- (double)multiply3:(double)f1 :(double)f2;
@end
Методы инициализации
Правило немного отличается для методов init
, где по умолчанию все параметры имеют внешнее имя. Например, это работает:
class Calc {
init(start: Int) {}
init(_ start: String) {}
}
let c1 = Calc(start: 6)
let c2 = Calc("6")
Здесь вы должны указать start:
для перегрузки, которая принимает Int
, но вы должны опустить ее для перегрузки, которая принимает String
.
Замечание по совместимости: этот класс будет экспортироваться в Objective-C следующим образом:
@interface Calc
- (instancetype)initWithStart:(NSInteger)start __attribute__((objc_designated_initializer));
- (instancetype)init:(NSString *)start __attribute__((objc_designated_initializer));
@end
Затворы
Предположим, что вы определяете тип замыкания следующим образом:
typealias FancyFunction = (f1: Double, f2: Double) -> Double
Имена параметров будут очень похожи на имена параметров в методе. Вам нужно будет указать имена параметров при вызове закрытия, если вы явно не установили внешнее имя _.
Например, выполнение закрытия:
fund doSomethingInteresting(withFunction: FancyFunction) {
withFunction(f1: 1.0, f2: 3.0)
}
Как правило, даже если вы им не нравитесь, вы должны, вероятно, попытаться использовать именованные параметры, по крайней мере, когда два параметра имеют один и тот же тип, чтобы их устранить. Я также утверждаю, что хорошо также назвать по крайней мере все параметры Int
и Boolean
.