Apa perwakilan _ garis bawah dalam Swift Referensi?

144

Di bagian referensi dokumen Apple ada banyak hal seperti ini:

func runAction(_action: SKAction!)

'Setara' Objective-C dari ini adalah:

- (void)runAction:(SKAction *)action

Itu mengejutkan saya bahwa mungkin penting bahwa (dalam referensi Swift) ada ruang setelah garis bawah dan "tindakan" ditulis dalam huruf miring.

Tetapi saya tidak tahu apa yang ingin disampaikannya. Jadi mungkin pertanyaannya adalah ... adakah referensi untuk konvensi yang digunakan dalam referensi?

- inilah halaman yang saya maksudkan dalam referensi ini untuk penggunaan garis bawah: https://developer.apple.com/documentation/spritekit/sknode#//apple_ref/occ/instm/SKNode/runAction

Memperbarui

Swift 3 telah membuat beberapa perubahan pada bagaimana nama parameter fungsi / metode dan label argumen digunakan dan dinamai. Ini memiliki konsekuensi pada pertanyaan ini dan jawabannya. @Rickster melakukan pekerjaan luar biasa untuk menjawab pertanyaan yang berbeda tentang _underscores dalam fungsi yang membersihkan sebagian besar dari ini, di sini: Mengapa saya perlu menggarisbawahi dengan cepat?

Bingung
sumber
3
Ditandai dengan [underscore.js] ??
Martin R
3
Dokumentasi ini mengikuti konvensi matematika menggunakan huruf miring untuk nama variabel. Sebagai contoh: sin² a + cos² a = 1.
rob mayoff

Jawaban:

116

Kedua jawaban itu benar tetapi saya ingin menjelaskan sedikit lebih banyak.

_digunakan untuk memodifikasi perilaku nama parameter eksternal untuk metode .

Di bagian Parameter Nama Lokal dan Eksternal untuk Metode dokumentasi, dikatakan:

Swift memberikan nama parameter pertama dalam metode nama parameter lokal secara default, dan memberikan nama parameter kedua dan selanjutnya nama parameter lokal dan eksternal secara default.

Di sisi lain, fungsi secara default tidak memiliki nama parameter eksternal.

Sebagai contoh, kita memiliki foo()metode ini didefinisikan di kelas Bar:

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

Ketika Anda menelepon foo(), ini disebut seperti bar.foo("Hello", s2: "World").

Tapi , Anda bisa mengesampingkan perilaku ini dengan menggunakan _di depan s2tempat itu dinyatakan.

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

Kemudian, ketika Anda menelepon foo, itu bisa disebut seperti bar.foo("Hello", "World")tanpa nama parameter kedua.

Kembali ke kasus Anda, runActionadalah metode karena itu terkait dengan tipe SKNode, jelas. Dengan demikian, menempatkan _parameter sebelum actionmemungkinkan Anda untuk memanggil runActiontanpa nama eksternal.

Pembaruan untuk Swift 2.0

Fungsi dan metode sekarang bekerja dengan cara yang sama dalam hal deklarasi nama argumen lokal dan eksternal.

Fungsi sekarang dipanggil dengan menggunakan nama parameter eksternal secara default, mulai dari parameter ke-2. Aturan ini hanya berlaku untuk kode Swift murni.

Jadi, dengan memberikan _di depan fungsi , pemanggil tidak harus menentukan nama parameter eksternal, seperti apa yang akan Anda lakukan untuk suatu metode .

Aaron He
sumber
9
Bingung, jika _menulis sebelum parameter kedua, jawaban Anda cukup jelas; bagaimana jika dalam func runAction(_action: SKAction!), _sebelum parameter pertama atau jika Anda menulis kode berikut func foo(_ s1: String) { // your code }Xcode akan memberi Anda peringatan, tetapi ada banyak kode seperti func bringSubviewToFront(_ view: UIView)dalam referensi, mengapa?
Will Zhang
10
jadi pada dasarnya, ia melakukan ini tanpa alasan dan hanya membingungkan semua orang. luar biasa.
botbot
2
Underscore dikenal sebagai 'Pola Wildcard' developer.apple.com/library/ios/documentation/Swift/Conceptual/...
user2143356
@ Wyatt Zhang, kata doc, bahwa penggunaan _untuk parameter pertama tidak relevan. Saya dapat membuat asumsi, bahwa para desainer berpikir itu jelas cukup untuk kode Anda dan tidak meningkatkan keterbacaan, sebaliknya, itu mengotori kode. Jadi, Anda mendapatkan peringatan itu. Referensi memiliki tujuan yang berlawanan: harus sejelas mungkin - sehingga garis bawah parameter pertama disebutkan untuk setiap metode. Itu akan menjelaskan semuanya)
Dmitry Gryazin
4
Penting untuk dicatat bahwa Swift 3.0 mengubah banyak hal. Semua label diperlukan, kecuali jika Anda menentukan sebaliknya. Jadi -sebelum parameter pertama tidak lagi asing. Misalnya: override func viewWillAppear(_ animated: Bool)memberi sinyal bahwa penelepon (kode Objective-C) tidak akan menggunakan label parameter
Tn.
85

Garis bawah adalah token umum yang digunakan untuk menunjukkan nilai yang dibuang.

Dalam kasus khusus ini, itu berarti bahwa fungsi akan dipanggil sebagai runAction(argument)gantirunAction(action:argument)

Dalam konteks lain ia memiliki makna serupa lainnya, misalnya dalam:

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

Itu berarti bahwa kami hanya ingin mengeksekusi blok 5 kali dan kami tidak peduli dengan indeks di dalam blok.

Dalam konteks ini:

let (result, _) = someFunctionThatReturnsATuple()

Itu berarti bahwa kita tidak peduli apa elemen kedua dari tuple, hanya yang pertama.

David Berry
sumber
Jadi dalam hal ini argumen (tindakan) adalah opsi?
Bingung
1
Tidak, itu menyebabkan nama parameter eksternal (tindakan :) dalam kasus ini, menjadi kosong, sehingga dihilangkan. Argumen masih diperlukan, hanya saja tidak ditandai dengan tindakan :.
David Berry
4
Jawaban sebenarnya adalah kombinasi dari jawaban @ dasblinkenlight dan milik saya. Dia menangani kasus spesifik ini lebih tepatnya, sedangkan tambang menjawab pertanyaan yang lebih luas, apa maksudnya?
David Berry
4
Anda juga dapat menggunakan tanda buangan untuk angka yang sangat besar agar lebih mudah dibaca seperti inilet pi = 3.141_592_653_59
SMP
lucu, Anda juga dapat menggunakannya untuk membuat angka yang sangat besar kurang dapat dibaca, sepertilet pi = 3.1_4_15_92___63
David Berry
15

Karena Swift 3 semua label argumen diperlukan secara default .

Anda dapat memaksa IDE untuk menyembunyikan label argumen _.

func foo(a: String) {
}

func foo2(_ a: String) {
}

menelepon foo(a: "abc")danfoo2("abc")

Catatan: ini hanya dapat digunakan ketika aadalah label argumen (eksternal) dan nama variabel (internal) pada waktu yang sama. Ini setara - func foo(a a: String)tidak akan menerima _.

Mengapa Apple menggunakannya?

Anda dapat melihat Apple menggunakannya di seluruh API. Pustaka Apple masih ditulis dalam Objective-C (jika tidak, mereka tetap memiliki nama fungsi yang sama, yang dirancang untuk sintaks Objective-C)

Fungsi seperti applicationWillResignActive(_ application: UIApplication)akan berlebihan nama parameter application, karena sudah ada yang aplikasi di dalamnya nama fungsi.

Contoh anda

func runAction(_ action: SKAction!)akan disebut tanpa itu _tanda seperti runAction(action:). Nama parameter actionakan berlebihan karena sudah ada satu di nama fungsi. Itulah tujuannya dan mengapa itu ada di sana.

Jakub Truhlář
sumber
13

Pengidentifikasi di depan deklarasi parameter mendefinisikan nama parameter eksternal . Ini adalah nama yang harus disediakan oleh pemanggil saat memanggil fungsi:

func someFunction(externalParameterName localParameterName: Int)

Swift memberikan nama eksternal otomatis untuk parameter default apa pun yang Anda tetapkan, jika Anda sendiri tidak memberikan nama eksternal. Menggunakan garis bawah untuk nama parameter eksternal menyisih dari perilaku ini:

Anda dapat memilih keluar dari perilaku ini dengan menulis garis bawah ( _) alih-alih nama eksternal eksplisit ketika Anda menentukan parameter.

Anda dapat membaca lebih lanjut tentang perilaku ini di bagian Nama Eksternal untuk Parameter dengan Nilai Default di sini .

dasblinkenlight
sumber
jadi ... biarkan aku melihat apakah kekurangtahuanku benar. Dalam contoh ini saya harus memberi nama variabel parameter saya / konstanta sebagai "action" dan menetapkannya ke SKAction yang ingin saya jalankan dengan fungsi ini, dan Swift secara otomatis memberi nama parameter default "action" yang diperlukan. NAMUN, jika saya ingin menamai tindakan ini kustom saya harus menggunakan garis bawah dalam pemanggilan fungsi?
Bingung
4
@Confused Pemahaman saya adalah bahwa SKdesainer tidak ingin Anda menulis actiondua kali, karena "action" sudah menjadi bagian dari nama fungsi. Dengan kata lain, mereka tidak ingin Anda menulis sprite.runAction(action:moveGroundSpritesForever). Tujuan dari nama parameter eksternal adalah untuk membuat kode Anda "dibaca seperti kalimat"; menggunakan actiondua kali akan mengalahkan tujuan itu.
dasblinkenlight
Beberapa lampu menyala dalam kegelapan. Saya rasa saya mengerti. Fitur bahasa ini dimaksudkan untuk membuat fungsi panggilan di Swift terlihat sangat mirip dengan cara Anda memanggil metode dengan parameter di Objective-C. Mungkin.
Bingung
1
Namun garis bawah dapat digunakan untuk memilih keluar entah dari mana memiliki nama parameter eksternal ini untuk parameter yang ditentukan dengan nilai default ... hanya belum melihat bagaimana hal itu dilakukan, belum. Akan terus mencari.
Bingung
Jadi ... singkatnya, ini hanya beralih antara parameter bernama dan parameter ordinal, sehingga Anda dapat dengan mudah beralih di antara foo.bar(param: 'fiddle') dan foo.bar('fiddle') CATATAN: dengan hanya satu argumen itu benar-benar tidak menjadi jelas ... tetapi dengan beberapa argumen itu menjadi sangat relevan: foo.bar(param1: 'fiddle', param2: 'dee') vs foo.bar('fiddle','dee')
jrypkahauer
10

Saya pikir ini memaksa konvensi di Swift yang membuatnya lebih dekat ke objektif-c, yang lebih cocok dengan konvensi kakao. Di objc Anda tidak (secara eksternal) memberi nama parameter pertama Anda. Sebagai gantinya, dengan konvensi Anda biasanya memasukkan nama eksternal di bagian akhir nama metode seperti ini:

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

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

Untuk membuat panggilan api Swift konsisten dengan objc Anda akan ingin menekan nama parameter eksternal param pertama.

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

someInstance.myFancyMethodWithFirstName("John", lastName:"Doe")
smileBot
sumber
2
Saya suka penjelasan ini. Setelah mempelajari Obj-C terlebih dahulu, Anda telah membereskan semuanya. Ini juga menyoroti pentingnya penamaan Metode dengan tepat di Swift, yaitu, bagian terakhir dari nama Metode harus menggambarkan argumen pertama, seperti yang biasanya terjadi pada Obj-C. barang bagus.
rrrrrraul
5

Sebenarnya, ada perbedaan antara kode nyata yang digunakan untuk mendefinisikan metode dan deklarasi metode dalam dokumen Apple. Mari kita ambil UIControl 's - addTarget: action: forControlEvents: metode misalnya, kode sebenarnya adalah: masukkan deskripsi gambar di sini

Namun dalam dokumen, ini tampak seperti ini (perhatikan _ sebelum target): masukkan deskripsi gambar di sini

Dalam kode nyata, _ digunakan untuk membuat nama eksternal parameter kedua atau berikutnya tidak muncul ketika suatu metode dipanggil, sementara dalam dokumen, _ sebelum nama lokal parameter menunjukkan bahwa ketika Anda memanggil suatu metode atau fungsi, Anda tidak boleh memberikan nama eksternal.

Tidak ada nama eksternal ketika suatu fungsi dipanggil secara default kecuali Anda memberikan sendiri atau menambahkan # sebelum (tanpa spasi) nama lokal parameter, misalnya, ini adalah bagaimana kami menggunakan dispatch_after : masukkan deskripsi gambar di sini

Dan dalam dokumen, tampak seperti ini (perhatikan tiga _): masukkan deskripsi gambar di sini

Konvensi deklarasi fungsi sama seperti yang saya jelaskan untuk metode.

fujianjin6471
sumber
1

Hanya lebih secara visual.

masukkan deskripsi gambar di sini

Seperti yang Anda lihat, _hapus saja nama parameter lokal atau tidak.

Nik Kov
sumber