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 tertulisPertanyaan 1Pertimbangkan 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
jawabannyatutorial1.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 2Anda 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
jawabannyaYa, 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
Namun, UIView adalah kelas dengan semantik referensial, sehingga Anda dapat mengubah properti view2 - yang berarti kode akan
dikompilasi .
Pertanyaan 3Kode 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)
jawabannyaSwift
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 4Kode 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?
jawabannyaAlamat 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 lisanPertanyaan 1Apa yang
opsional dan masalah apa yang mereka pecahkan?
jawabannyaopsional 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 2Tuliskan secara singkat perbedaan utama antara
struktur dan
kelas .
jawabannyaKelas mendukung warisan, tetapi struktur tidak.
Kelas adalah tipe referensi, struktur adalah tipe nilai.
Pertanyaan 3Apa itu
obat generik dan untuk apa?
jawabannyaDi 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")
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 4Dalam beberapa kasus, tidak mungkin untuk menghindari opsi yang secara implisit tidak
terbuka . Kapan dan mengapa?
jawabannyaAlasan 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 5Apa sajakah cara untuk menggunakan opsional? Nilai mereka dalam hal keamanan.
var x : String? = "Test"
Petunjuk: Hanya 7 cara.
jawabannyaMembuka 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 tertulisPertanyaan 1Apa perbedaan antara
nil dan
.tidak ada ?
jawabannyaTidak 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 2Berikut 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)
jawabannyaThermometerStruct 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 3Apa yang akan dihasilkan kode ini dan mengapa?
var thing = "cars" let closure = { [thing] in print("I love \(thing)") } thing = "airplanes" closure()
jawabannyaAkan 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()
Pertanyaan 4Ini 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])
Tulis ulang fungsi ini sebagai ekstensi Array sehingga Anda dapat menggunakannya seperti ini:
[1, 2, 3, 3].countUniques()
catatan penerjemahSesuatu 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 5Berikut 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.
jawabannyaPernyataan
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 6Tulis ulang metode dari pertanyaan 5 menggunakan pernyataan
if let .
jawabannyaPernyataan 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 lisanPertanyaan 1Di Objective-C, Anda mendeklarasikan konstanta seperti ini:
const int number = 0;
Demikian juga dalam Swift:
let number = 0
Apa bedanya?
jawabannyaDalam
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 2Untuk 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.
jawabannyastatis 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() }
Pertanyaan 3Apakah mungkin menambahkan
properti yang disimpan ke jenis menggunakan
ekstensi ? Bagaimana atau mengapa tidak?
jawabannyaTidak, 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 4Apa protokol di Swift?
jawabannyaProtokol 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 tertulisPertanyaan 1Misalkan 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?
jawabannyaSwift 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 2Swift 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
jawabannyaMembuat 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 3Kode 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()
jawabannyaDi 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 4Kode 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.
jawabannyaBlok
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 lisanPertanyaan 1Apakah penutupan merupakan tipe referensi atau tipe nilai?
jawabannyaPenutupan 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 2Anda 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?
jawabannyaAda penginisialisasi untuk ini:
UInt(bitPattern: Int)
Dan gunakan:
let myNegative = UInt(bitPattern: -1)
Pertanyaan 3Jelaskan referensi melingkar di Swift? Bagaimana mereka bisa diperbaiki?
jawabannyaReferensi 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 4Swift 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?
jawabannyaKami lupa kata kunci
tidak langsung , yang memungkinkan opsi enumerasi rekursif serupa:
enum List<T> { indirect case node(T, List<T>) }