Wawancara: Cepat. Tanya Jawab

Bahasa pemrograman Swift baru berusia empat tahun, tetapi sudah menjadi bahasa pengembangan utama untuk iOS. Berkembang ke versi 5.0, Swift telah menjadi bahasa yang kompleks dan kuat yang memenuhi paradigma berorientasi objek dan fungsional. Dan dengan setiap rilis baru, itu menambah lebih banyak fitur.

Tetapi seberapa baik Anda benar - benar mengenal Swift? Pada artikel ini, Anda akan menemukan contoh pertanyaan untuk wawancara Swift.

Anda dapat menggunakan pertanyaan ini untuk mewawancarai kandidat untuk menguji pengetahuan mereka atau Anda dapat menguji sendiri. Jika Anda tidak tahu jawabannya, jangan khawatir: ada jawaban untuk setiap pertanyaan.

Pertanyaan dibagi menjadi tiga kelompok:

  • Pemula : untuk pemula. Anda membaca beberapa buku dan menerapkan Swift di aplikasi Anda sendiri.
  • Menengah : cocok untuk mereka yang benar-benar tertarik dengan bahasa tersebut. Anda sudah membaca banyak tentang itu dan sering bereksperimen.
  • Advanced : cocok untuk pengembang paling maju - mereka yang suka masuk ke hutan sintaksis dan menggunakan teknik-teknik canggih.

Ada dua jenis pertanyaan untuk setiap level:

  • ditulis : cocok untuk pengujian melalui email, karena mereka menyarankan penulisan kode.
  • lisan : dapat digunakan ketika berbicara di telepon atau secara langsung, karena ada cukup jawaban dalam kata-kata.

Saat Anda membaca artikel ini, biarkan taman bermain terbuka untuk dapat memeriksa kode dari pertanyaan. Semua jawaban telah diuji pada Xcode 10.2 dan Swift 5 .

  • Pemula


    pertanyaan tertulis
    Pertanyaan 1
    Pertimbangkan kode berikut:

    struct Tutorial { var difficulty: Int = 1 } var tutorial1 = Tutorial() var tutorial2 = tutorial1 tutorial2.difficulty = 2 

    Apa nilai-nilai tutorial1.difficulty dan tutorial2.difficulty ? Apakah ada perbedaan jika Tutorial itu kelas? Mengapa

    jawabannya
    tutorial1.difficulty adalah 1, dan tutorial2.difficulty adalah 2.

    Dalam Swift, struktur adalah tipe nilai. Mereka disalin, bukan dirujuk. Baris berikut menyalin tutorial1 dan menugaskannya ke tutorial2 :

     var tutorial2 = tutorial1 

    Perubahan pada tutorial2 tidak mempengaruhi tutorial1 .

    Jika Tutorial adalah sebuah kelas, tutorial1.difficulty dan tutorial2.difficulty akan sama 2. Kelas di Swift adalah tipe referensi. Ketika Anda mengubah properti tutorial1, Anda akan melihat perubahan yang sama untuk tutorial2 - dan sebaliknya.


    Pertanyaan 2
    Anda mendeklarasikan view1 dengan var dan view2 dengan let . Apa perbedaannya dan apakah baris terakhir dikompilasi?

     import UIKit var view1 = UIView() view1.alpha = 0.5 let view2 = UIView() view2.alpha = 0.5 //   ? 

    jawabannya
    Ya, baris terakhir dikompilasi. view1 adalah variabel, dan Anda dapat menetapkan nilainya ke instance UIView yang baru. Dengan menggunakan let , Anda hanya dapat menetapkan nilai sekali, sehingga kode berikut ini tidak dapat dikompilasi:

     view2 = view1 // : view2 is immutable 

    Namun, UIView adalah kelas dengan semantik referensial, sehingga Anda dapat mengubah properti view2 - yang berarti kode akan dikompilasi .

    Pertanyaan 3
    Kode ini mengurutkan array berdasarkan abjad. Sederhanakan penutupan sebanyak mungkin.

     var animals = ["fish", "cat", "chicken", "dog"] animals.sort { (one: String, two: String) -> Bool in return one < two } print(animals) 

    jawabannya
    Swift secara otomatis menentukan tipe parameter penutupan dan tipe pengembalian, sehingga Anda dapat menghapusnya :

     animals.sort { (one, two) in return one < two } 

    Anda dapat mengganti nama parameter menggunakan notasi $ i :

     animals.sort { return $0 < $1 } 

    Penutupan yang terdiri dari satu pernyataan mungkin tidak mengandung kata kunci kembali . Nilai pernyataan terakhir yang dieksekusi menjadi hasil pengembalian penutupan:

     animals.sort { $0 < $1 } 

    Akhirnya, karena Swift tahu bahwa elemen-elemen array sesuai dengan protokol Equatable , Anda cukup menulis:

     animals.sort(by: <) 


    Upd: hummingbirddj bahkan lebih disederhanakan:
    Dalam hal ini, Anda bahkan bisa lebih pendek:
      animals.sort() 
    - Macam naik, bekerja untuk jenis yang mengimplementasikan Sebanding.


    Pertanyaan 4
    Kode ini menciptakan dua kelas: Alamat dan Orang . Dua instance dari kelas Person ( Ray dan Brian ) juga dibuat.

     class Address { var fullAddress: String var city: String init(fullAddress: String, city: String) { self.fullAddress = fullAddress self.city = city } } class Person { var name: String var address: Address init(name: String, address: Address) { self.name = name self.address = address } } var headquarters = Address(fullAddress: "123 Tutorial Street", city: "Appletown") var ray = Person(name: "Ray", address: headquarters) var brian = Person(name: "Brian", address: headquarters) 

    Misalkan Brian telah pindah ke alamat baru dan Anda ingin memperbarui catatannya sebagai berikut:

     brian.address.fullAddress = "148 Tutorial Street" 

    Ini mengkompilasi dan berjalan tanpa kesalahan. Tetapi, jika Anda memeriksa sekarang alamat Ray , maka Anda akan melihat bahwa dia juga "pindah" .

    Apa yang terjadi di sini dan bagaimana cara memperbaikinya?

    jawabannya
    Alamat adalah kelas dan memiliki semantik referensi . Jadi, markas adalah contoh yang sama dari kelas yang digunakan oleh ray dan brian. Mengubah kantor pusat akan mengubah alamat keduanya.
    Untuk memperbaikinya, Anda bisa membuat instance baru dari kelas Address dan menugaskannya ke Brian, atau mendeklarasikan Address sebagai struct sebagai ganti kelas .

    pertanyaan lisan
    Pertanyaan 1
    Apa yang opsional dan masalah apa yang mereka pecahkan?

    jawabannya
    opsional memungkinkan variabel jenis apa pun menyajikan situasi " tidak ada nilai ". Di Objective-C, "tidak ada nilai" hanya tersedia dalam tipe referensi menggunakan nilai khusus nihil . Jenis nilai, seperti int atau float , tidak memiliki kemampuan ini.
    Swift telah memperluas konsep "tidak ada nilai" ke tipe nilai. Variabel opsional dapat berisi nilai atau nihil , yang menunjukkan tidak adanya nilai.


    Pertanyaan 2
    Tuliskan secara singkat perbedaan utama antara struktur dan kelas .

    jawabannya
    Kelas mendukung warisan, tetapi struktur tidak.
    Kelas adalah tipe referensi, struktur adalah tipe nilai.


    Pertanyaan 3
    Apa itu obat generik dan untuk apa?

    jawabannya
    Di Swift, Anda bisa menggunakan obat generik di kelas, struktur, dan enumerasi.

    Generik memperbaiki masalah duplikasi kode. Jika Anda memiliki metode yang menerima parameter dari satu jenis, kadang-kadang Anda harus menduplikasi kode untuk bekerja dengan parameter dari jenis lain.

    Sebagai contoh, dalam kode ini fungsi kedua adalah "klon" dari yang pertama, kecuali bahwa ia memiliki parameter string, bukan integer.

     func areIntEqual(_ x: Int, _ y: Int) -> Bool { return x == y } func areStringsEqual(_ x: String, _ y: String) -> Bool { return x == y } areStringsEqual("ray", "ray") // true areIntEqual(1, 1) // true 

    Menggunakan obat generik, Anda menggabungkan dua fungsi dalam satu dan pada saat yang sama memastikan keamanan jenis:

     func areTheyEqual<T: Equatable>(_ x: T, _ y: T) -> Bool { return x == y } areTheyEqual("ray", "ray") areTheyEqual(1, 1) 

    Karena Anda menguji kesetaraan, Anda membatasi tipe pada yang sesuai dengan protokol Equatable . Kode ini memberikan hasil yang diinginkan dan mencegah transfer parameter dari tipe yang salah.


    Pertanyaan 4
    Dalam beberapa kasus, tidak mungkin untuk menghindari opsi yang secara implisit tidak terbuka . Kapan dan mengapa?

    jawabannya
    Alasan paling umum untuk menggunakan opsi tersirat secara implisit adalah:

    • ketika Anda tidak dapat menginisialisasi properti yang tidak nol pada saat pembuatan. Contoh khas adalah outlet di Interface Builder, yang selalu diinisialisasi setelah pemiliknya. Dalam kasus khusus ini, jika semuanya dikonfigurasikan dengan benar di Interface Builder, Anda dijamin bahwa outlet tidak nol sebelum menggunakannya.
    • untuk menyelesaikan masalah loop dari referensi kuat ketika dua instance kelas mereferensi satu sama lain dan referensi non-nil ke instance lain diperlukan. Dalam hal ini, Anda menandai tautan di satu sisi sebagai tidak dimiliki , dan di sisi lain menggunakan ekspansi opsional implisit.


    Pertanyaan 5
    Apa sajakah cara untuk menggunakan opsional? Nilai mereka dalam hal keamanan.

     var x : String? = "Test" 

    Petunjuk: Hanya 7 cara.

    jawabannya
    Membuka paksa secara paksa tidak aman.

     let a: String = x! 

    Penerapan implisit saat mendeklarasikan variabel tidak aman.

     var a = x! 

    Ikatan opsional aman.

     if let a = x { print("x was successfully unwrapped and is = \(a)") } 

    Chaining opsional aman.

     let a = x?.count 

    Operator penggabungan nol tidak aman.

     let a = x ?? "" 

    Pernyataan Penjaga aman.

     guard let a = x else { return } 

    Pola opsional - aman.

     if case let a? = x { print(a) } 




  • Menengah


    pertanyaan tertulis
    Pertanyaan 1
    Apa perbedaan antara nil dan .tidak ada ?

    jawabannya
    Tidak ada perbedaan, Optional.none (singkat .none ) dan nil adalah setara.
    Bahkan, pernyataan berikut akan mengembalikan true :

     nil == .none 


    Menggunakan nihil lebih umum diterima dan direkomendasikan.


    Pertanyaan 2
    Berikut ini adalah model termometer dalam bentuk kelas dan struktur. Kompiler mengeluh tentang baris terakhir. Apa yang salah di sana?

     public class ThermometerClass { private(set) var temperature: Double = 0.0 public func registerTemperature(_ temperature: Double) { self.temperature = temperature } } let thermometerClass = ThermometerClass() thermometerClass.registerTemperature(56.0) public struct ThermometerStruct { private(set) var temperature: Double = 0.0 public mutating func registerTemperature(_ temperature: Double) { self.temperature = temperature } } let thermometerStruct = ThermometerStruct() thermometerStruct.registerTemperature(56.0) 

    jawabannya
    ThermometerStruct dideklarasikan dengan benar dengan fungsi bermutasi untuk mengubah variabel internal. Kompiler mengeluh bahwa Anda memanggil metode registerTemperature dari instance yang dibuat dengan let , jadi instance ini tidak dapat diubah. Mengubah let to var akan memperbaiki kesalahan kompilasi.

    Dalam struktur, Anda harus menandai metode yang mengubah variabel internal sebagai bermutasi , tetapi Anda tidak dapat memanggil metode ini menggunakan instance yang tidak dapat diubah.


    Pertanyaan 3
    Apa yang akan dihasilkan kode ini dan mengapa?

     var thing = "cars" let closure = { [thing] in print("I love \(thing)") } thing = "airplanes" closure() 


    jawabannya
    Akan dicetak: Saya suka mobil. Daftar tangkap akan membuat salinan variabel ketika penutupan dinyatakan. Ini berarti bahwa variabel yang ditangkap tidak akan mengubah nilainya, bahkan setelah menetapkan nilai baru.

    Jika Anda menghilangkan daftar tangkap di penutupan, maka kompiler akan menggunakan tautan, bukan salinannya. Panggilan penutupan akan mencerminkan perubahan dalam variabel:

     var thing = "cars" let closure = { print("I love \(thing)") } thing = "airplanes" closure() // Prints: "I love airplanes" 



    Pertanyaan 4
    Ini adalah fungsi yang menghitung jumlah nilai unik dalam array:

     func countUniques<T: Comparable>(_ array: Array<T>) -> Int { let sorted = array.sorted() let initial: (T?, Int) = (.none, 0) let reduced = sorted.reduce(initial) { ($1, $0.0 == $1 ? $0.1 : $0.1 + 1) } return reduced.1 } 

    Ini menggunakan diurutkan, jadi itu hanya menggunakan tipe yang sesuai dengan protokol Sebanding.

    Anda bisa menyebutnya seperti ini:

     countUniques([1, 2, 3, 3]) //  3 


    Tulis ulang fungsi ini sebagai ekstensi Array sehingga Anda dapat menggunakannya seperti ini:

     [1, 2, 3, 3].countUniques() //   3 


    catatan penerjemah
    Sesuatu yang terlalu menyakitkan adalah fungsi yang mengerikan. Kenapa tidak:

     func countUniques<T: Hashable>(_ array: Array<T>) -> Int { return Set(array).count } 


    jawabannya
     extension Array where Element: Comparable { func countUniques() -> Int { let sortedValues = sorted() let initial: (Element?, Int) = (.none, 0) let reduced = sortedValues.reduce(initial) { ($1, $0.0 == $1 ? $0.1 : $0.1 + 1) } return reduced.1 } } 



    Pertanyaan 5
    Berikut adalah fungsi yang membagi dua ganda opsional. Ada tiga syarat yang harus dipenuhi:
    • dividen tidak boleh nol
    • pembagi tidak boleh nol
    • pembagi tidak boleh 0


     func divide(_ dividend: Double?, by divisor: Double?) -> Double? { if dividend == nil { return nil } if divisor == nil { return nil } if divisor == 0 { return nil } return dividend! / divisor! } 

    Menulis ulang fungsi ini menggunakan pernyataan penjaga dan tidak menggunakan membuka paksa.
    jawabannya
    Pernyataan penjaga yang diperkenalkan di Swift 2.0 memberikan jalan keluar jika kondisinya tidak terpenuhi. Berikut ini sebuah contoh:

     guard dividend != nil else { return nil } 


    Anda juga dapat menggunakan pernyataan penjaga untuk penjilidan opsional , setelah itu variabel yang diperluas akan tersedia di luar pernyataan penjaga :

     guard let dividend = dividend else { return .none } 


    Jadi, Anda dapat menulis ulang fungsi seperti ini:

     func divide(_ dividend: Double?, by divisor: Double?) -> Double? { guard let dividend = dividend else { return nil } guard let divisor = divisor else { return nil } guard divisor != 0 else { return nil } return dividend / divisor } 

    Perhatikan kurangnya pembongkaran paksa, karena kami telah membongkar dividen dan pembagi dan menempatkannya dalam variabel tidak berubah opsional.

    Perhatikan juga bahwa hasil opsional yang tidak dibongkar dalam pernyataan penjaga juga tersedia di luar pernyataan penjaga.

    Anda selanjutnya dapat menyederhanakan fungsi dengan mengelompokkan pernyataan penjaga:

     func divide(_ dividend: Double?, by divisor: Double?) -> Double? { guard let dividend = dividend, let divisor = divisor, divisor != 0 else { return nil } return dividend / divisor } 



    Pertanyaan 6
    Tulis ulang metode dari pertanyaan 5 menggunakan pernyataan if let .

    jawabannya
    Pernyataan if let memungkinkan Anda untuk membongkar opsional dan menggunakan nilai ini di dalam blok kode ini. Di luar itu, nilai-nilai ini tidak akan tersedia.

     func divide(_ dividend: Double?, by divisor: Double?) -> Double? { if let dividend = dividend, let divisor = divisor, divisor != 0 { return dividend / divisor } else { return nil } } 




    pertanyaan lisan
    Pertanyaan 1
    Di Objective-C, Anda mendeklarasikan konstanta seperti ini:

     const int number = 0; 

    Demikian juga dalam Swift:

     let number = 0 

    Apa bedanya?

    jawabannya
    Dalam Objective-C, konstanta diinisialisasi pada waktu kompilasi dengan nilai yang harus diketahui pada titik ini.

    Nilai abadi yang dibuat dengan let adalah konstanta yang didefinisikan pada saat run time . Anda dapat menginisialisasi dengan ekspresi statis atau dinamis. Karena itu, kita dapat melakukan ini:

     let higherNumber = number + 5 


    Harap perhatikan bahwa penugasan semacam itu hanya dapat dilakukan satu kali.


    Pertanyaan 2
    Untuk mendeklarasikan properti atau fungsi statis untuk tipe nilai, pengubah statis digunakan. Berikut adalah contoh untuk struktur:

     struct Sun { static func illuminate() {} } 

    Dan untuk kelas dimungkinkan untuk menggunakan pengubah statis atau kelas . Hasilnya sama, tetapi ada perbedaan. Jelaskan.

    jawabannya
    statis membuat properti atau fungsi menjadi statis dan tidak tumpang tindih . Menggunakan kelas akan menimpa properti atau fungsi.

    Di sini kompiler akan bersumpah atas upaya untuk mengesampingkan illuminate () :

     class Star { class func spin() {} static func illuminate() {} } class Sun : Star { override class func spin() { super.spin() } // error: class method overrides a 'final' class method override static func illuminate() { super.illuminate() } } 



    Pertanyaan 3
    Apakah mungkin menambahkan properti yang disimpan ke jenis menggunakan ekstensi ? Bagaimana atau mengapa tidak?

    jawabannya
    Tidak, ini tidak mungkin. Kita bisa menggunakan ekstensi untuk menambahkan perilaku baru ke tipe yang sudah ada, tetapi kita tidak bisa mengubah tipe itu sendiri atau antarmuka-nya. Untuk menyimpan properti yang baru disimpan, kami membutuhkan memori tambahan, dan ekstensi tidak dapat melakukan ini.


    Pertanyaan 4
    Apa protokol di Swift?

    jawabannya
    Protokol adalah tipe yang mendefinisikan garis besar metode, properti, dll. Kelas, struktur, atau enumerasi dapat menggunakan protokol untuk mengimplementasikan semua ini. Protokol itu sendiri tidak mengimplementasikan fungsionalitas, tetapi mendefinisikannya.



  • Mahir


    pertanyaan tertulis
    Pertanyaan 1
    Misalkan kita memiliki struktur yang mendefinisikan model termometer:

     public struct Thermometer { public var temperature: Double public init(temperature: Double) { self.temperature = temperature } } 

    Untuk membuat sebuah instance, kami menulis:

     var t: Thermometer = Thermometer(temperature:56.8) 

    Tetapi sesuatu seperti ini akan jauh lebih nyaman:

     var thermometer: Thermometer = 56.8 

    Apakah ini mungkin? Bagaimana?

    jawabannya
    Swift mendefinisikan protokol yang memungkinkan Anda untuk menginisialisasi jenis menggunakan literal dengan tugas. Menerapkan protokol yang sesuai dan menyediakan inisialisasi publik akan memungkinkan inisialisasi menggunakan literal. Dalam kasus Thermometer, kami menerapkan ExpressibleByFloatLiteral :

     extension Thermometer: ExpressibleByFloatLiteral { public init(floatLiteral value: FloatLiteralType) { self.init(temperature: value) } } 


    Sekarang kita dapat membuat instance seperti ini:

     var thermometer: Thermometer = 56.8 



    Pertanyaan 2
    Swift memiliki seperangkat operator yang telah ditentukan sebelumnya untuk operasi aritmatika dan logis. Ini juga memungkinkan Anda untuk membuat operator Anda sendiri, baik unary dan binary.

    Tentukan dan laksanakan operator eksponensial Anda sendiri (^^) sesuai dengan persyaratan berikut:
    • mengambil dua int sebagai parameter
    • mengembalikan hasil menaikkan parameter pertama ke kekuatan parameter kedua
    • dengan benar memproses urutan operasi aljabar
    • mengabaikan kemungkinan kesalahan overflow


    jawabannya
    Membuat operator baru terjadi dalam dua tahap: pengumuman dan implementasi.

    Deklarasi ini menggunakan kata kunci operator untuk menentukan jenis (unary atau binary), untuk menentukan urutan karakter dari operator baru, asosiasi dan senioritas pelaksanaannya.

    Di sini operatornya ^^ dan tipenya adalah infix (biner). Asosiatif benar.

    Swift tidak memiliki senioritas yang telah ditentukan sebelumnya untuk eksponensial. Dalam aljabar, eksponensial harus dihitung sebelum perkalian / pembagian. Dengan demikian, kami membuat pesanan eksekusi khusus dengan menempatkan eksponensial lebih tinggi dari multiplikasi.

    Pengumuman ini:

     precedencegroup ExponentPrecedence { higherThan: MultiplicationPrecedence associativity: right } infix operator ^^: ExponentPrecedence 


    Ini implementasinya:

     func ^^(base: Int, exponent: Int) -> Int { let l = Double(base) let r = Double(exponent) let p = pow(l, r) return Int(p) } 



    Pertanyaan 3
    Kode berikut mendefinisikan struktur Pizza dan protokol Pizzeria dengan ekstensi untuk implementasi default metode makeMargherita () :

     struct Pizza { let ingredients: [String] } protocol Pizzeria { func makePizza(_ ingredients: [String]) -> Pizza func makeMargherita() -> Pizza } extension Pizzeria { func makeMargherita() -> Pizza { return makePizza(["tomato", "mozzarella"]) } } 


    Sekarang kita mendefinisikan restoran Lombardis :

     struct Lombardis: Pizzeria { func makePizza(_ ingredients: [String]) -> Pizza { return Pizza(ingredients: ingredients) } func makeMargherita() -> Pizza { return makePizza(["tomato", "basil", "mozzarella"]) } } 

    Kode berikut membuat dua contoh Lombardis . Siapa di antara mereka yang membuat margarita dengan kemangi?

     let lombardis1: Pizzeria = Lombardis() let lombardis2: Lombardis = Lombardis() lombardis1.makeMargherita() lombardis2.makeMargherita() 


    jawabannya
    Di keduanya. Protokol Pizzeria mendeklarasikan metode makeMargherita () dan menyediakan implementasi default. Implementasi Lombardis menggantikan metode default. Karena kami mendeklarasikan metode dalam protokol di dua tempat, implementasi yang benar akan dipanggil.

    Tetapi bagaimana jika protokol tidak menyatakan metode makeMargherita () , dan ekstensi masih menyediakan implementasi default, seperti ini:

     protocol Pizzeria { func makePizza(_ ingredients: [String]) -> Pizza } extension Pizzeria { func makeMargherita() -> Pizza { return makePizza(["tomato", "mozzarella"]) } } 

    Dalam hal ini, hanya lombardis2 yang memiliki pizza dengan basil, sedangkan lombardis1 tidak memiliki pizza, karena akan menggunakan metode yang ditentukan dalam ekstensi.


    Pertanyaan 4
    Kode berikut tidak dikompilasi. Bisakah Anda menjelaskan apa yang salah dengannya? Sarankan solusi untuk masalah tersebut.

     struct Kitten { } func showKitten(kitten: Kitten?) { guard let k = kitten else { print("There is no kitten") } print(k) } 

    Petunjuk: Ada tiga cara untuk memperbaiki kesalahan.


    jawabannya
    Blok lain dari pernyataan penjaga memerlukan opsi keluar, baik menggunakan kembali , melempar pengecualian atau memanggil @noreturn . Solusi paling sederhana adalah dengan menambahkan pernyataan kembali .

     func showKitten(kitten: Kitten?) { guard let k = kitten else { print("There is no kitten") return } print(k) } 

    Solusi ini akan mengeluarkan pengecualian:

     enum KittenError: Error { case NoKitten } struct Kitten { } func showKitten(kitten: Kitten?) throws { guard let k = kitten else { print("There is no kitten") throw KittenError.NoKitten } print(k) } try showKitten(kitten: nil) 


    Akhirnya, ini adalah panggilan ke fatalError () , fungsi @noreturn .

     struct Kitten { } func showKitten(kitten: Kitten?) { guard let k = kitten else { print("There is no kitten") fatalError() } print(k) } 




    pertanyaan lisan
    Pertanyaan 1
    Apakah penutupan merupakan tipe referensi atau tipe nilai?

    jawabannya
    Penutupan adalah tipe referensi. Jika Anda menetapkan penutupan pada variabel dan kemudian menyalinnya ke variabel lain, Anda menyalin tautan ke penutupan yang sama dan daftar tangkapnya.


    Pertanyaan 2
    Anda menggunakan tipe UInt untuk menyimpan integer yang tidak ditandatangani. Itu mengimplementasikan penginisialisasi untuk mengkonversi dari keseluruhan dengan tanda:

     init(_ value: Int) 

    Namun, kode berikut ini tidak dapat dikompilasi jika Anda menetapkan nilai negatif:

     let myNegative = UInt(-1) 

    Bilangan bulat yang ditandatangani, menurut definisi, tidak boleh negatif. Namun, dimungkinkan untuk menggunakan representasi dari angka negatif dalam memori untuk menerjemahkannya menjadi unsigned.

    Bagaimana saya bisa mengkonversi bilangan bulat negatif ke UInt sambil mempertahankan perwakilannya di memori?

    jawabannya
    Ada penginisialisasi untuk ini:

     UInt(bitPattern: Int) 


    Dan gunakan:

     let myNegative = UInt(bitPattern: -1) 



    Pertanyaan 3
    Jelaskan referensi melingkar di Swift? Bagaimana mereka bisa diperbaiki?

    jawabannya
    Referensi melingkar terjadi ketika dua instance berisi referensi kuat satu sama lain, yang mengarah pada kebocoran memori karena kenyataan bahwa tidak satu pun dari instance ini dapat dibebaskan. Sebuah instance tidak dapat dibebaskan sementara masih ada referensi kuat untuk itu, tetapi satu instance memegang yang lainnya.

    Ini dapat diatasi dengan mengganti tautan di satu sisi dengan menetapkan kata kunci lemah atau tidak dimiliki .


    Pertanyaan 4
    Swift memungkinkan Anda membuat enumerasi rekursif. Berikut ini adalah contoh dari enumerasi yang berisi varian Node dengan dua tipe asosiatif, T dan Daftar:

     enum List<T> { case node(T, List<T>) } 

    Akan ada kesalahan kompilasi. Apa yang kami lewatkan?

    jawabannya
    Kami lupa kata kunci tidak langsung , yang memungkinkan opsi enumerasi rekursif serupa:

     enum List<T> { indirect case node(T, List<T>) } 




Source: https://habr.com/ru/post/id449410/


All Articles