Що є _ представником підкреслення у Swift References?


144

У довідковому розділі документів Apple є багато таких випадків:

func runAction(_action: SKAction!)

"Еквівалент" цілі-C цього:

- (void)runAction:(SKAction *)action

Мене вражає, що, мабуть, важливо, щоб (у посиланні Swift) було пробіл після того, як підкреслення та "дія" написано курсивом.

Але я не можу зрозуміти, що це намагається передати. Тож, можливо, питання полягає в тому ... чи існує посилання на конвенції, що використовуються в посиланнях?

- ось сторінка, на яку я посилаюсь у цьому посиланні на використання підкреслення: https://developer.apple.com/documentation/spritekit/sknode#//apple_ref/occ/instm/SKNode/runAction

Оновлення

Swift 3 внесла деякі зміни в спосіб використання імен імен параметрів функції / методу та міток аргументів. Це має наслідки щодо цього питання та його відповіді. @Rickster виконує дивовижну роботу, відповідаючи на інше запитання про _underscores у функціях, які очищають значну частину цього, тут: навіщо мені потрібні підкреслення швидко?


3
З тегом [underscore.js] ??
Мартін Р

3
Документація дотримується математичної конвенції щодо використання курсиву для назв змінних. Наприклад: sin² a + cos² a = 1.
пограбувати майоф

Відповіді:


116

Обидві відповіді були правильними, але я хочу ще трохи уточнити.

_використовується для зміни поведінки імен зовнішніх параметрів для методів .

У розділі документації " Імена локальних і зовнішніх параметрів для методів " зазначено:

Swift дає першому імені параметра в методі місцеве ім'я параметра за замовчуванням і дає другий і наступні імена параметрів як локальні, так і зовнішні імена параметрів за замовчуванням.

З іншого боку, функції за замовчуванням не мають зовнішніх імен параметрів.

Наприклад, у нас цей foo()метод визначений у класі Bar:

class Bar{
    func foo(s1: String, s2: String) -> String {
        return s1 + s2;
    }
}

Коли ви телефонуєте foo(), це називається як bar.foo("Hello", s2: "World").

Але ви можете змінити цю поведінку, використовуючи _перед тим, s2де це оголошено.

func foo(s1: String, _ s2: String) -> String{
    return s1 + s2;
}

Тоді, коли ви телефонуєте foo, його можна було просто викликати як bar.foo("Hello", "World")без імені другого параметра.

Повернення до вашої справи runAction- це метод, оскільки він SKNode, очевидно , пов'язаний з типом . Таким чином, розміщення _параметра "перш" actionдозволяє дзвонити runActionбез зовнішнього імені.

Оновлення для Swift 2.0

Функція та метод тепер працюють однаково в плані оголошення локального та зовнішнього аргументу.

Тепер функції викликаються, використовуючи за замовчуванням ім'я зовнішнього параметра, починаючи з 2-го параметра. Це правило стосується лише чистого коду Swift.

Таким чином, забезпечуючи функцію _перед функцією , абоненту не доведеться вказувати ім'я зовнішнього параметра, як і те, що ви робите для методу .


9
Плутати, якщо _записувати перед другим параметром, ваша відповідь досить однозначно; що якщо в func runAction(_action: SKAction!), то _перед першим параметром або якщо ви пишете наступний код, func foo(_ s1: String) { // your code }Xcode попередить вас, але код є багато, як func bringSubviewToFront(_ view: UIView)у посиланні, чому?
Вілл Чжан

10
так в основному, це робить це без причини і просто бентежить усіх. приголомшливий
бот

2
Підкреслення відоме як розробник «
Шаблону

@Wyatt Zhang, доктор каже, що використання _першого параметра є стороннім. Я можу зробити припущення, що дизайнери вважають, що, очевидно, достатньо для вашого коду і не збільшують читабельність, навпаки, це забруднює код. Так ви отримуєте попередження. Посилання має протилежну мету: вона повинна бути максимально чіткою, тому підкреслення першого параметра згадується для КОЖНОГО методу. Це все б пояснило)
Дмитро Грязін

4
Важливо зазначити, що Swift 3.0 змінює речі. Усі етикетки потрібні, якщо не вказано інше. Тож -раніше перший параметр вже не сторонній. Наприклад: override func viewWillAppear(_ animated: Bool)сигналізує про те, що абонент (код Objective-C) не буде використовувати мітку параметрів
Містер T

85

Підкреслення - загальний маркер, який використовується для позначення відкинутого значення.

У цьому конкретному випадку це означає, що функція буде викликана як runAction(argument)замістьrunAction(action:argument)

В інших контекстах воно має інше подібне значення, наприклад, у:

for _ in 0..<5 { ... }

Це означає, що ми просто хочемо виконати блок 5 разів і нам не байдуже індекс всередині блоку.

У цьому контексті:

let (result, _) = someFunctionThatReturnsATuple()

Це означає, що нам байдуже, що є другим елементом кортежу, лише першим.


Тож у цьому випадку аргумент (дія) є варіантом?
Плутати

1
Ні, це призводить до того, що назва зовнішнього параметра (дія :) в цьому випадку порожнє, таким чином, пропускається. Аргумент все-таки потрібен, він просто не позначений дією:.
Девід Беррі

4
Справжня відповідь - це поєднання відповіді @ dasblinkenlight і моєї. Він вирішує цей конкретний випадок точніше, тоді як мій стосується більш широкого питання, що означає _?
Девід Беррі

4
Ви можете використовувати знак відкидання також для дуже великих чисел, щоб зробити їх більш читабельними, як цеlet pi = 3.141_592_653_59
SMP

кумедно, ви також можете використовувати його, щоб зробити дуже великі числа менш читабельними, як-отlet pi = 3.1_4_15_92___63
Девід Беррі

15

Оскільки Swift 3, усі мітки аргументів за замовчуванням потрібні .

Ви можете змусити IDE приховати мітку аргументу за допомогою _.

func foo(a: String) {
}

func foo2(_ a: String) {
}

називається foo(a: "abc")іfoo2("abc")

Примітка: Це може бути використано тільки тоді , коли aце етикетка (зовнішній) аргумент і (внутрішній) ім'я змінної , в той же час. Це рівноцінно - func foo(a a: String)не приймемо _.

Чому Apple використовує його?

Ви можете бачити, що Apple використовує його в API. Бібліотеки Apple все ще записуються в Objective-C (якщо ні, то в будь-якому випадку вони мають однакові назви функцій, які були розроблені для синтаксису Objective-C)

Функції, як-от, applicationWillResignActive(_ application: UIApplication)мали б зайве ім'я параметра application, оскільки в його імені функції вже є додаток .

Ваш приклад

func runAction(_ action: SKAction!)буде називатися без його _позначки runAction(action:). Назва параметра actionбула б зайвою, оскільки в імені функції вона вже є. Ось яка мета і чому вона там є.


13

Ідентифікатор перед оголошенням параметра визначає ім'я зовнішнього параметра. Це ім'я, яке повинен надати абонент при виклику функції:

func someFunction(externalParameterName localParameterName: Int)

Swift надає автоматичне зовнішнє ім'я для будь-якого визначеного вами параметра, який не визначається, якщо ви самостійно не вказали зовнішнє ім'я. Використання підкреслення для імені зовнішнього параметра відмовляється від такої поведінки:

Ви можете відмовитися від такої поведінки, написавши підкреслення ( _) замість явного зовнішнього імені, коли визначаєте параметр.

Детальніше про цю поведінку ви можете прочитати в розділі « Зовнішні імена для параметрів із значеннями за замовчуванням тут» .


тож ... дозвольте мені побачити, чи моє розмиття отримало це право. У цьому прикладі я повинен назвати мінливу / константу параметру як "дія" і призначити її SKAction, який я хочу запустити за допомогою цієї функції, і Swift автоматично назвать необхідний параметр за замовчуванням "дія". ЯКЩО, якщо я хочу вподобати назву цієї дії, я повинен використовувати підкреслення під час виклику функції?
Плутати

4
@Confused Моє розуміння полягає в тому SK, що дизайнери не хочуть, щоб ви писали actionдвічі, тому що "дія" вже є частиною назви функції. Іншими словами, вони не хочуть, щоб ви писали sprite.runAction(action:moveGroundSpritesForever). Мета зовнішніх назв параметрів полягала в тому, щоб зробити ваш код "прочитаним як речення"; використання actionдвічі перемогло б мету.
dasblinkenlight

Деякі вогники згасали в темряві. Я думаю, я це зрозумів. Ця функція мови призначена для того, щоб функції виклику в Swift виглядали так, як ви б викликали метод з параметрами в Objective-C. Може бути.
Плутати

1
Однак підкреслення можна використати, щоб якось відмовитися від наявності цих зовнішніх імен параметрів для параметрів, визначених за замовчуванням ... просто ще не бачили, як це робиться. Буде продовжувати шукати.
Плутати

Отже, коротше кажучи, він просто перемикається між названими параметрами та порядковими параметрами, так що ви можете легко перемикатися між foo.bar(param: 'fiddle') і foo.bar('fiddle') ПРИМІТКА: лише з одним аргументом він дійсно не стає очевидним ... але з кількома аргументами він стає дуже актуальним: foo.bar(param1: 'fiddle', param2: 'dee') vs foo.bar('fiddle','dee')
jrypkahauer

10

Я думаю, що це змушує конвенцію у Свіфті, яка змушує її читати ближче до Objective-c, яка краще відповідає умовам какао. У objc ви не (зовні) не називаєте свій перший параметр. Натомість за умовою ви зазвичай включаєте зовнішнє ім'я в останню частину назви методу, як це:

- (void)myFancyMethodWithFirstName:(NSString *)aFirstName lastName:(NSString *)aLastName;

[someInstance myFancyMethodWithFirstName:@"John" lastName:@"Doe"];

Для того, щоб Swift api-дзвінки відповідали objc, вам потрібно придушити ім'я зовнішнього параметра першого парамуму.

func myFancyMethodWithFirstName(_ firstName:String, lastName:String);

someInstance.myFancyMethodWithFirstName("John", lastName:"Doe")

2
Мені подобається це пояснення. дізнавшись спочатку Obj-C, ви прояснили речі. Він також підкреслює важливість відповідного іменування методу у Swift, а саме остання частина назви методу повинна описувати перший аргумент, як це зазвичай відбувається у Obj-C. Хороший матеріал.
rrrrrraul

5

Насправді, існує різниця між реальним кодом, який використовується для визначення методу, та декларацією методу в документах Apple. Візьмемо, наприклад, UIControl 's - addTarget: action: forControlEvents: метод, реальний код: введіть тут опис зображення

Але в документах воно виглядає так (зауважте _ перед ціллю): введіть тут опис зображення

У реальному коді _ використовується для того, щоб зовнішнє ім'я другого або наступних параметрів не з’являлося під час виклику методу , в той час як в документах _ перед локальним іменем параметра вказується, що при виклику методу чи функції ви не повинні надавати зовнішня назва.

Немає зовнішнього імені, коли функція викликається за замовчуванням, якщо ви не вказали своє власне або додали # раніше (без пробілу) локальне ім'я параметра, наприклад, таким чином ми використовуємо dispatch_after : введіть тут опис зображення

А в документах це виглядає так (помічте три _): введіть тут опис зображення

Конвенція декларації функції точно така ж, як я описав для методу.


1

Просто більш візуально.

введіть тут опис зображення

Як ви бачите, _просто зробити пропустіть ім'я локального параметра чи ні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.