Indonesian (Bahasa Indonesia) translation by Andy Nur (you can also view the original English article)
Sementara tutorial ini berfokus terutama pada fungsi dan penutupan, kami mengambil jalan memutar singkat pada akhir untuk mengeksplorasi protokol dan kontrol akses. Kami akan bekerja dengan protokol nanti dalam seri ini sehingga sangat penting untuk menjadi akrab dengan mereka sejak awal.
Beberapa bulan yang lalu, aku menulis seri tentang bahasa pemrograman cepat di mana aku mengambil melihat dari dekat fungsi dan penutupan. Artikel ini meringkas apa yang saya tulis di tutorial ini. Jika Anda ingin informasi lebih lanjut tentang fungsi dan penutupan, saya sarankan membaca artikel dari seri:
Sebelum kita menyelam ke dalam topik fungsi dan penutupan, saatnya untuk api up Xcode dan menciptakan sebuah taman bermain baru. Siap? Mari kita menulis beberapa kode.
1. fungsi
Apa itu fungsi?
Fungsi adalah tidak lebih dari satu blok kode yang dapat dijalankan saat dibutuhkan. Saya ingin memulai dengan contoh untuk membahas anatomi dasar dari suatu fungsi dalam Swift. Tambahkan definisi fungsi berikut untuk bermain.
1 |
func printHelloWorld() { |
2 |
print("Hello World!") |
3 |
}
|
Fungsi dimulai dengan kata kunci func dan diikuti oleh nama fungsi, printHelloWorld dalam contoh di atas. Seperti banyak bahasa lain, nama fungsi diikuti oleh sepasang kurung yang berisi parameter fungsi, fungsi input.
Tubuh fungsi dibungkus dalam sepasang kurung kurawal. Tubuh fungsi printHelloWorld() berisi satu pernyataan di mana kami mencetak string "Hello World!" dalam output standar. Ini adalah apa yang tampak seperti fungsi dasar di Swift. Untuk memanggil fungsi, kita ketik namanya diikuti oleh sepasang tanda kurung.
1 |
printHelloWorld() |
Parameter
Mari kita membuat contoh di atas agak lebih kompleks dengan menambahkan parameter ke definisi fungsi. Dengan menambahkan parameter, kami menyediakan fungsi dengan nilai input yang dapat digunakan dalam tubuhnya. Dalam contoh berikut, kita mendefinisikan fungsi printMessage(_:), yang menerima satu parameter, pesan, tipe String.
1 |
func printMessage(message: String) { |
2 |
print(message) |
3 |
}
|
Fungsi dapat menerima beberapa parameter atau nilai input. Parameter dibungkus dengan kurung yang mengikuti nama fungsi. Nama parameter diikuti oleh usus besar dan jenis. Seperti yang Anda ingat, ini sangat mirip dengan mendeklarasikan variabel atau konstan. Ini hanya mengatakan bahwa parameter pesan adalah tipe String.
Menerapkan fungsi ini mirip dengan apa yang kita lihat sebelumnya. Perbedaannya adalah bahwa kita melewati dalam sebuah argumen.
1 |
printMessage("Hello World!") |
Contoh berikut tampak serupa. Satu-satunya perbedaan adalah bahwa fungsi yang mendefinisikan dua parameter, pesan jenis String dan kali jenis Int.
1 |
func printMessage(message: String, times: Int) { |
2 |
for i in 0..<times { |
3 |
print("\(i) \(message)") |
4 |
}
|
5 |
}
|
Sementara nama fungsi identik dengan yang asli printMessage(_:) fungsi, fungsi yang jenis berbeda. Penting bahwa Anda memahami perbedaan ini. Fungsi masing-masing memiliki tipe, terdiri dari parameter jenis dan tipe kembali. Kita akan mengeksplorasi jenis kembali dalam sekejap. Fungsi dapat memiliki nama yang sama sebagai tipe mereka berbeda seperti yang ditunjukkan oleh definisi fungsi dua sebelumnya.
Jenis fungsi pertama adalah (String)-> () sementara jenis fungsi kedua (String, Int)-> (). Nama kedua fungsi adalah sama. Jangan khawatir tentang-> simbol. Maknanya akan menjadi jelas dalam beberapa saat ketika kita membahas jenis kembali.
Yang kedua adalah fungsi printMessage(_:times:) mendefinisikan dua parameter, pesan jenis String dan kali jenis Int. Tanda-tangan fungsi ini menggambarkan salah satu fitur Swift telah mengadopsi dari Objective-C, dapat dibaca fungsi dan nama metode.
1 |
printMessage("Hello World!", times: 3) |
Jenis kembali
Fungsi-fungsi yang telah kita lihat sejauh tidak kembali apa-apa kepada kami ketika kami memanggil mereka. Mari kita membuat sebuah fungsi yang format tanggal. Fungsi mengambil dua argumen, tanggal jenis NSDate dan string format tipe String. Karena NSDate dan NSDateFormatter kelas yang didefinisikan dalam kerangka dasar, kita perlu mengimpor Yayasan di atas Taman Bermain.
1 |
import Foundation |
2 |
|
3 |
func formatDate(date: NSDate, format: String = "YY/MM/dd") -> String { |
4 |
let dateFormatter = NSDateFormatter() |
5 |
dateFormatter.dateFormat = format |
6 |
return dateFormatter.stringFromDate(date) |
7 |
}
|
Ada beberapa hal yang perlu beberapa penjelasan. -> Simbol menunjukkan bahwa fungsi mengembalikan nilai. Jenis nilai didefinisikan setelah-> simbol, String.
Fungsi yang menerima dua argumen dan argumen kedua memiliki nilai default. Hal ini ditunjukkan dengan tugas berikut jenis argumen kedua. Nilai default format adalah "YY/MM/dd". Ini berarti bahwa kita dapat memanggil fungsi dengan hanya satu argumen. Xcode's autocompletion menggambarkan hal ini.



Jika fungsi tidak memiliki tipe pengembalian,-> simbol dihilangkan. Itu sebabnya fungsi printHelloWorld() tidak memiliki-> simbol dalam definisi metode.
Nama Parameter lokal dan eksternal
Sebelumnya dalam tutorial ini, kita mendefinisikan fungsi printMessage(_:). Meskipun kami telah memberikan parameter nama, pesan, kami tidak menggunakan nama itu ketika kita memanggil fungsi. Sebaliknya, kita hanya lulus dalam nilai untuk parameter pesan.
1 |
func printMessage(message: String) { |
2 |
print(message) |
3 |
}
|
4 |
|
5 |
printMessage("Hello World!") |
Nama kita mendefinisikan dalam definisi fungsi adalah nama parameter lokal. Nilai parameter dapat hanya direferensi dengan nama ini dalam tubuh fungsi. Tetapi parameter fungsi sedikit lebih fleksibel daripada itu.
Tujuan-C dikenal dengan nama metode lama. Sementara ini mungkin terlihat kikuk dan janggal luar, itu membuat metode mudah untuk memahami dan, jika dipilih dengan baik, sangat deskriptif. Jika Anda berpikir Anda kehilangan manfaat ini ketika beralih ke Swift, maka Anda berada di sebuah kejutan.
Ketika fungsi menerima beberapa parameter, itu tidak selalu jelas argumen yang sesuai dengan parameter yang. Lihatlah contoh berikut untuk lebih memahami masalah.
1 |
func power(a: Int, b: Int) -> Int { |
2 |
var result = a |
3 |
|
4 |
for _ in 1..<b { |
5 |
result = result * a |
6 |
}
|
7 |
|
8 |
return result |
9 |
}
|
10 |
|
11 |
power(2, 3) |
Fungsi power(_:b:) menimbulkan nilai oleh b eksponen. Parameter kedua adalah dari jenis Int. Sementara kebanyakan orang secara intuitif akan melewati nilai dasar sebagai argumen pertama dan eksponen sebagai argumen kedua, ini tidak jelas dari jenis fungsi, nama atau tanda tangan.
Untuk menghindari kebingungan, kami dapat memberikan parameter fungsi nama eksternal. Kita dapat menggunakan nama-nama ini eksternal ketika fungsi disebut jelas menunjukkan argumen yang sesuai dengan parameter yang. Lihatlah contoh di bawah diperbarui.
1 |
func power(base a: Int, exponent b: Int) -> Int { |
2 |
var result = a |
3 |
|
4 |
for _ in 1..<b { |
5 |
result = result * a |
6 |
}
|
7 |
|
8 |
return result |
9 |
}
|
Catatan bahwa fungsi tubuh tidak berubah, karena nama lokal belum berubah. Namun, ketika kita memanggil fungsi diperbarui, perbedaannya adalah jelas dan hasilnya jauh lebih sedikit membingungkan.
1 |
power(base: 2, exponent: 3) |
Meskipun jenis kedua fungsi yang sama, (Int, Int)-> Int, fungsi berbeda. Dengan kata lain, yang kedua adalah fungsi tidak redeclaration fungsi pertama. Sintaks untuk memanggil fungsi kedua mungkin mengingatkan Anda beberapa Objective-C. Tidak hanya adalah argumen yang jelas dijelaskan, kombinasi dari nama-nama fungsi dan parameter menjelaskan tujuan dari fungsi.
Di Swift, parameter pertama, secara default, tidak memiliki eksternal parameter nama. Itu sebabnya tanda tangan dari fungsi printMessage(_:) termasuk _ untuk parameter pertama. Jika kita ingin menentukan nama parameter eksternal untuk parameter pertama, definisi metode akan terlihat sedikit berbeda.
1 |
func printMessage(message message: String) { |
2 |
print(message) |
3 |
}
|
4 |
|
5 |
printMessage(message: "Hello World!") |
Fungsi-fungsi global dan bersarang
Contoh-contoh yang telah kita lihat sejauh ini dikenal sebagai fungsi-fungsi global, karena mereka sedang didefinisikan di lingkup global. Fungsi dapat juga diulang. Bersarang fungsi hanya dapat disebut lingkup yang ditetapkan. Ini berarti bahwa fungsi bersarang hanya dapat disebut dari fungsi yang didefinisikan. Contoh berikutnya menjelaskan ini.
1 |
func printMessage(message: String) { |
2 |
let a = "hello world" |
3 |
|
4 |
func printHelloWorld() { |
5 |
print(a) |
6 |
}
|
7 |
}
|
2. penutupan
Apa yang dimaksud dengan penutupan?
Jika Anda telah bekerja dengan blok C dan Objective-C atau penutupan dalam JavaScript, maka Anda tidak akan memiliki waktu sulit membungkus kepala Anda di sekitar konsep penutupan. Kami telah sudah bekerja dengan penutupan dalam artikel ini, karena fungsi juga penutupan. Mari kita mulai dengan dasar-dasar dan memeriksa anatomi penutupan.
Penutupan adalah sebuah blok fungsi yang dapat Anda berikan di sekitar di kode. Anda dapat melewati penutupan sebagai argumen fungsi atau Anda dapat menyimpannya sebagai properti dari objek. Penutupan memiliki banyak kasus penggunaan.
Penutupan nama petunjuk pada salah satu karakteristik utama dari penutupan. Penutupan menangkap variabel dan konstanta konteks di mana itu didefinisikan. Ini kadang-kadang disebut sebagai penutup atas variabel dan konstanta tersebut.
Sintaks
Sintaks dasar penutupan tidak sulit. Lihatlah contoh berikut.
1 |
let a = {(a: Int) -> Int in |
2 |
return a + 1 |
3 |
}
|
Hal pertama yang Anda perhatikan adalah bahwa penutupan seluruh dibungkus dalam sepasang kurung kurawal. Parameter penutupan dibungkus dalam sepasang tanda kurung, terpisah dari jenis kembali oleh-> simbol. Penutupan di atas menerima satu argumen,, tipe Int dan mengembalikan Int. Tubuh penutupan dimulai setelah kata kunci di.
Bernama penutupan, yaitu fungsi-fungsi global dan bersarang, terlihat sedikit berbeda. Contoh berikut menggambarkan perbedaan-perbedaan ini.
1 |
func increment(a: Int) -> Int { |
2 |
return a + 1 |
3 |
}
|
Perbedaan yang paling menonjol adalah penggunaan kata kunci func dan posisi parameter dan tipe pengembalian. Penutupan dimulai dan diakhiri dengan penjepit keriting, pembungkus parameter, jenis kembali, dan tubuh. Meskipun perbedaan-perbedaan ini, ingat bahwa setiap fungsi adalah penutupan. Tidak setiap penutupan adalah fungsi, meskipun.
Penutupan sebagai parameter
Penutupan kuat dan contoh berikut menggambarkan bagaimana berguna mereka dapat. Dalam contoh, kami menciptakan sebuah array Serikat. Kita memanggil fungsi map() pada array menciptakan array baru yang hanya berisi huruf pertama dua dari setiap negara sebagai string dikapitalisasi.
1 |
var states = ["California", "New York", "Texas", "Alaska"] |
2 |
|
3 |
let abbreviatedStates = states.map({ (state: String) -> String in |
4 |
let index = state.startIndex.advancedBy(2) |
5 |
return state.substringToIndex(index).uppercaseString |
6 |
})
|
7 |
|
8 |
print(abbreviatedStates) |
Dalam contoh di atas, map() fungsi dipanggil pada array Serikat, mengubah isinya, dan mengembalikan array baru yang berisi nilai berubah. Contoh juga menunjukkan kekuatan Swift jenis kesimpulan. Karena kita memanggil fungsi map() array string, Swift tahu bahwa argumen negara adalah tipe String. Ini berarti bahwa kita dapat menghilangkan jenis seperti ditunjukkan pada contoh di bawah diperbarui.
1 |
let abbreviations = states.map({ (state) -> String in |
2 |
return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString |
3 |
})
|
Ada beberapa hal yang kita dapat menghilangkan dari contoh di atas, mengakibatkan satu-kapal berikut.
1 |
let abbreviations = states.map({ state in state.substringToIndex(state.startIndex.advancedBy(2)).uppercaseString }) |
Biarkan saya menjelaskan apa yang terjadi. Kompilator dapat menyimpulkan bahwa kita mengembalikan sebuah string dari penutupan bahwa kita melewati ke fungsi map(), yang berarti tidak ada alasan untuk memasukkan jenis kembali dalam penutupan ekspresi definisi. Kita hanya bisa melakukan ini jika penutupan badan mencakup pernyataan tunggal, meskipun. Dalam hal ini, kita dapat menempatkan pernyataan itu pada baris yang sama sebagai definisi penutupan, seperti ditunjukkan pada contoh di atas. Karena tidak ada jenis kembali dalam definisi dan tidak-> simbol sebelumnya jenis kembali, kita dapat menghilangkan tanda kurung yang melampirkan penutupan parameter.
Nama-nama argumen singkatan
Itu tidak berhenti di sini, meskipun. Kami dapat menggunakan nama-nama argumen singkatan untuk menyederhanakan ekspresi penutupan di atas bahkan lebih. Ketika menggunakan ekspresi penutupan inline, seperti pada contoh di atas, kita dapat menghilangkan daftar parameter, termasuk kata kunci di yang memisahkan parameter dari tubuh penutupan.
Dalam penutupan tubuh, kita referensi menggunakan singkatan nama argumen Swift memberikan kita dengan argumen. Argumen pertama direferensikan oleh $0, yang kedua oleh $1, dll.
Dalam contoh diperbarui di bawah ini, saya telah dihilangkan daftar parameter dan kata kunci di, dan diganti argumen negara dalam penutupan tubuh dengan singkatan nama argumen $0. Pernyataan yang dihasilkan lebih singkat tanpa mengorbankan mudah dibaca.
1 |
let abbreviations = states.map({ $0.substringToIndex($0.startIndex.advancedBy(2)).uppercaseString }) |
Trailing penutupan
Bahasa pemrograman yang cepat juga mendefinisikan konsep yang dikenal sebagai trailing penutupan. Jika Anda melewatkan penutupan sebagai argumen terakhir fungsi, Anda dapat menempatkan penutupan yang di luar kurung panggilan fungsi. Contoh berikut menunjukkan bagaimana ini bekerja.
1 |
let abbreviations = states.map() { $0.substringToIndex($0.startIndex.advancedBy(2)).uppercaseString } |
Jika argumen hanya panggilan fungsi penutupan, maka mungkin untuk menghilangkan tanda kurung panggilan fungsi.
1 |
let abbreviations = states.map { $0.substringToIndex($0.startIndex.advancedBy(2)).uppercaseString } |
Catatan bahwa ini juga bekerja untuk penutupan yang berisi beberapa pernyataan. Pada kenyataannya, itu adalah alasan utama trailing penutupan tersedia di Swift. Jika penutupan yang panjang atau rumit dan itu merupakan argumen terakhir dari fungsi, hal ini sering lebih baik untuk menggunakan sintaks penutupan trailing.
1 |
let abbreviations = states.map { (state: String) -> String in |
2 |
let toIndex = state.startIndex.advancedBy(2) |
3 |
let newState = state.substringToIndex(toIndex) |
4 |
return newState.uppercaseString |
5 |
}
|
3. protokol
Protokol adalah komponen penting dari bahasa pemrograman yang cepat. Konsep tidak sulit untuk mengerti jika Anda terbiasa dengan protokol di Objective-C atau antarmuka di Jawa. Sebuah protokol mendefinisikan desain atau antarmuka terfokus pada tugas tertentu. Hal ini dilakukan dengan mendefinisikan properti dan metode yang diperlukan untuk melakukan tugas itu.
Mendefinisikan sebuah protokol terlihat mirip mendefinisikan kelas atau struktur. Dalam contoh berikut, kita mendefinisikan protokol yang dapat diperbaiki. Protokol mendefinisikan dua sifat, waktu dan biaya dan repair() metode. Properti saat ini readonly sementara biaya properti readwrite.
1 |
protocol Repairable { |
2 |
var time: Float { get } |
3 |
var cost: Float { get set } |
4 |
|
5 |
func repair() |
6 |
}
|
Kelas atau struktur dapat mengadopsi sebuah protokol dengan menyesuaikan untuk itu. Ini berarti bahwa itu diperlukan untuk menerapkan properti dan metode yang didefinisikan oleh protokol. Mari kita memperbarui kelas perahu kami dilaksanakan dalam tutorial sebelumnya.
1 |
class Boat: Repairable { |
2 |
|
3 |
var speed: Float = 0 |
4 |
var lifeboats: Int = 2 |
5 |
|
6 |
var time: Float = 10.0 |
7 |
var cost: Float = 100.0 |
8 |
|
9 |
func deployLifeboats() { |
10 |
// ...
|
11 |
}
|
12 |
|
13 |
func repair() { |
14 |
// ...
|
15 |
}
|
16 |
|
17 |
}
|
Itu adalah bagaimana mudahnya untuk menyesuaikan jenis protokol. Meskipun sebuah protokol tidak dapat instantiated seperti kelas atau struktur, sebuah protokol adalah sejenis yang berlaku. Lihatlah contoh berikut di mana protokol dpt digunakan sebagai jenis argumen fungsi.
1 |
func bringInForRepairs(toBeRepaired: Repairable) { |
2 |
// ...
|
3 |
}
|
4 |
|
5 |
let myDamagedBoat = Boat() |
6 |
|
7 |
bringInForRepairs(myDamagedBoat) |
Davis Allie baru-baru ini menulis sebuah artikel besar tentang pemrograman berorientasi protokol di Swift. Jika Anda tertarik untuk belajar lebih lanjut tentang protokol dan potensi Swift, kemudian saya mendorong Anda untuk membaca artikel Davis'.
4. akses kontrol
Saya ingin untuk menyimpulkan pengantar Swift dengan berbicara tentang kontrol akses. Seperti namanya, kontrol akses mendefinisikan kode yang memiliki akses ke kode yang. Tingkat kontrol akses menerapkan metode, fungsi, jenis, dll. Apple hanya merujuk kepada entitas. Ada tiga tingkat kontrol akses, umum, internal, dan Pribadi.
- Umum: Entitas yang ditandai sebagai umum dapat diakses oleh entitas yang didefinisikan dalam modul yang sama serta modul lain, seperti proyek, kerangka kerja, atau Perpustakaan. Tingkat kontrol akses ini sangat ideal untuk mengekspos antarmuka kerangka.
- Internal: Ini adalah tingkat kontrol akses default. Dengan kata lain, jika tingkat kontrol akses tidak ditetapkan, tingkat kontrol akses internal berlaku. Sebuah entitas dengan tingkat akses internal ini hanya dapat diakses oleh entitas yang didefinisikan dalam modul yang sama.
- Pribadi: Sebuah entitas yang dinyatakan sebagai pribadi ini hanya dapat diakses oleh entitas yang ditentukan di file sumber yang sama.
Lihatlah contoh berikut di mana aku telah memperbarui kelas perahu. Kelas itu sendiri ditandai sebagai umum, yang berarti dapat diakses dari mana saja. Properti biaya implisit ditandai sebagai internal, karena kita belum ditentukan tingkat kontrol akses. Hal yang sama juga berlaku untuk metode deployLifeboats().
1 |
public class Boat { |
2 |
|
3 |
public var speed: Float = 0 |
4 |
public var lifeboats: Int = 2 |
5 |
|
6 |
var cost: UInt = 100 |
7 |
|
8 |
func deployLifeboats() { |
9 |
// ...
|
10 |
}
|
11 |
|
12 |
private func scheduleMaintenance() { |
13 |
|
14 |
}
|
15 |
}
|
Metode scheduleMaintenance() yang ditandai sebagai pribadi, yang berarti bahwa itu hanya akan dipanggil oleh entitas yang ditentukan di file sumber di mana kapal kelas didefinisikan. Hal ini penting untuk memahami hal ini, karena itu sedikit berbeda dari bahasa pemrograman lain mempertimbangkan pribadi metode atau properti.
Jika kita menandai kelas kapal sebagai internal dengan menghapus kata kunci umum, kompilator akan menunjukkan kepada kita peringatan. Hal itu menjelaskan bahwa kita tidak dapat menandai kecepatan dan sekoci sebagai publik selama perahu ditandai internal. Kompilator benar tentu saja. Tidak masuk akal untuk menandai sifat-sifat kelas internal sebagai umum.



Kesimpulan
Bahasa pemrograman Swift mudah untuk mengambil, tetapi ada jauh lebih dari apa yang kita telah membahas di masa lalu dua tutorial. Anda akan belajar lebih banyak tentang Swift setelah kita mulai membangun aplikasi. Dalam artikel berikutnya, kami mengambil melihat lebih dekat pada iOS SDK.
Jika Anda memiliki pertanyaan atau komentar, Anda dapat meninggalkan mereka di komentar di bawah atau mengulurkan tangan kepada saya di Twitter.