Swift - Rantai Opsional

Proses query, memanggil properti, subskrip dan metode pada opsional yang mungkin 'nil' didefinisikan sebagai rangkaian opsional. Rantai opsional mengembalikan dua nilai -

  • jika opsional berisi 'nilai' maka memanggil properti terkait, metode dan subskrip akan mengembalikan nilai

  • jika opsional berisi nilai 'nil', semua properti terkaitnya, metode dan subskrip akan mengembalikan nil

Karena beberapa queri ke metode, properti dan subskrip dikelompokkan bersama, kegagalan ke satu rantai akan memengaruhi seluruh rantai dan menghasilkan nilai 'nihil'.

Rangkaian Opsional sebagai Alternatif untuk Membuka Bungkus Paksa

Rangkaian opsional ditentukan setelah nilai opsional dengan '?' untuk memanggil properti, metode, atau subskrip ketika nilai opsional mengembalikan beberapa nilai.

Rantai Opsional '?' Akses ke metode, properti, dan langgananOpsional Chaining '!' untuk memaksa Membuka Bungkus
? ditempatkan setelah nilai opsional untuk memanggil properti, metode, atau subskrip ! ditempatkan setelah nilai opsional untuk memanggil properti, metode atau subskrip untuk memaksa membuka bungkusan nilai
Gagal dengan anggun saat opsionalnya 'nihil' Pembongkaran paksa memicu kesalahan waktu proses ketika opsionalnya adalah 'nil'

Program untuk Rantai Opsional dengan '!'

class ElectionPoll {
   var candidate: Pollbooth?
}

lass Pollbooth {
   var name = "MP"
}

let cand = ElectionPoll()
let candname = cand.candidate!.name

Ketika kami menjalankan program di atas menggunakan playground, kami mendapatkan hasil sebagai berikut -

fatal error: unexpectedly found nil while unwrapping an Optional value
0 Swift 4 0x0000000103410b68
llvm::sys::PrintStackTrace(__sFILE*) + 40
1 Swift 4 0x0000000103411054 SignalHandler(int) + 452
2 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 26
3 libsystem_platform.dylib 0x000000000000000b _sigtramp + 1854492939
4 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 1976783636
5 Swift 4 0x0000000102a85c39
llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 329
6 Swift 4 0x0000000102d320b3
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
std::__1::vector<std::__1::basic_string, std::__1::allocator >,
std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&,
char const* const*) + 1523
7 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift
4::CompilerInstance&, std::__1::vector<std::__1::basic_string,
std::__1::allocator >, std::__1::allocator<std::__1::basic_string,
std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptions
const&) + 1066
8 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef,
char const*, void*) + 5275
9 Swift 4 0x0000000102754a6d main + 1677
10 libdyld.dylib 0x00007fff8bb9e5c9 start + 1
11 libdyld.dylib 0x000000000000000c start + 1950751300
Stack dump:
0. Program arguments:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 -
target-cpu core2 -sdk
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/
SDKs/MacOSX10.10.sdk -module-name main
/bin/sh: line 47: 15672 Done cat <<'SWIFT 4'
import Foundation
</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std::
__1::basic_string

Program di atas mendeklarasikan 'polling pemilu' sebagai nama kelas dan berisi 'kandidat' sebagai fungsi keanggotaan. Subclass ini dinyatakan sebagai 'tempat pemungutan suara' dan 'nama' sebagai fungsi keanggotaannya yang diinisialisasi sebagai 'MP'. Panggilan ke kelas super diinisialisasi dengan membuat instance 'cand' dengan opsional '!'. Karena nilai tidak dideklarasikan dalam kelas dasarnya, nilai 'nil' disimpan sehingga mengembalikan kesalahan fatal dengan prosedur paksa membuka bungkus.

Program untuk Rantai Opsional dengan '?'

class ElectionPoll {
   var candidate: Pollbooth?
}

class Pollbooth {
   var name = "MP"
}
let cand = ElectionPoll()

if let candname = cand.candidate?.name {
   print("Candidate name is \(candname)")
} else {
   print("Candidate name cannot be retreived")
}

Ketika kami menjalankan program di atas menggunakan playground, kami mendapatkan hasil sebagai berikut -

Candidate name cannot be retreived

Program di atas mendeklarasikan 'polling pemilihan' sebagai nama kelas dan berisi 'kandidat' sebagai fungsi keanggotaan. Subclass ini dinyatakan sebagai 'tempat pemungutan suara' dan 'nama' sebagai fungsi keanggotaannya yang diinisialisasi sebagai 'MP'. Panggilan ke kelas super diinisialisasi dengan membuat instance 'cand' dengan opsional '?'. Karena nilai tidak dideklarasikan di kelas dasarnya, nilai 'nil' disimpan dan dicetak di konsol oleh blok penangan else.

Menentukan Kelas Model untuk Rangkaian Opsional & Mengakses Properti

Bahasa Swift 4 juga menyediakan konsep rangkaian opsional, untuk mendeklarasikan lebih dari satu subclass sebagai kelas model. Konsep ini akan sangat berguna untuk mendefinisikan model yang kompleks dan untuk mengakses properti, metode, dan sub properti sub-properti.

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var street: String?

   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let rectname = rectangle()
if let rectarea = rectname.print?.cprint {
   print("Area of rectangle is \(rectarea)")
} else {
   print("Rectangle Area is not specified")
}

Ketika kami menjalankan program di atas menggunakan playground, kami mendapatkan hasil sebagai berikut -

Rectangle Area is not specified

Metode Panggilan Melalui Rantai Opsional

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }

   func circleprint() {
      print("Area of Circle is: \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if circname.print?.circleprint() != nil {
   print("Area of circle is specified)")
} else {
   print("Area of circle is not specified")
}

Ketika kami menjalankan program di atas menggunakan playground, kami mendapatkan hasil sebagai berikut -

Area of circle is not specified

Fungsi circleprint () yang dideklarasikan di dalam sub kelas circle () dipanggil dengan membuat instance bernama 'circname'. Fungsi akan mengembalikan nilai jika berisi beberapa nilai jika tidak, fungsi akan mengembalikan beberapa pesan cetak yang ditentukan pengguna dengan memeriksa pernyataan 'if circname.print? .Circleprint ()! = Nil'.

Mengakses Langganan melalui Rantai Opsional

Rantai opsional digunakan untuk menyetel dan mengambil nilai subskrip untuk memvalidasi apakah panggilan ke subskrip tersebut mengembalikan nilai. '?' ditempatkan sebelum kurung siku untuk mengakses nilai opsional pada subskrip tertentu.

Program 1

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname =  radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if let radiusName = circname.print?[0].radiusname {
   print("The first room name is \(radiusName).")
} else {
   print("Radius is not specified.")
}

Ketika kami menjalankan program di atas menggunakan playground, kami mendapatkan hasil sebagai berikut -

Radius is not specified.

Dalam program di atas, nilai instance untuk fungsi keanggotaan 'radiusName' tidak ditentukan. Oleh karena itu, pemanggilan program ke fungsi hanya akan mengembalikan bagian lain sedangkan untuk mengembalikan nilai kita harus menentukan nilai untuk fungsi keanggotaan tertentu.

Program 2

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()

printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

if let radiusName = circname.print?[0].radiusname {
   print("Radius is measured in \(radiusName).")
} else {
   print("Radius is not specified.")
}

Ketika kami menjalankan program di atas menggunakan playground, kami mendapatkan hasil sebagai berikut -

Radius is measured in Units.

Dalam program di atas, nilai instance untuk fungsi keanggotaan 'radiusName' ditentukan. Oleh karena itu, pemanggilan program ke fungsi tersebut sekarang akan mengembalikan nilai.

Mengakses Langganan Jenis Opsional

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }

   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")

let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

var area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]]
area["Radius"]?[1] = 78
area["Circle"]?[1]--

print(area["Radius"]?[0])
print(area["Radius"]?[1])
print(area["Radius"]?[2])
print(area["Radius"]?[3])

print(area["Circle"]?[0])
print(area["Circle"]?[1])
print(area["Circle"]?[2])

Ketika kami menjalankan program di atas menggunakan playground, kami mendapatkan hasil sebagai berikut -

Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)

Nilai opsional untuk subskrip dapat diakses dengan merujuk nilai subskripnya. Ini dapat diakses sebagai subskrip [0], subskrip [1] dll. Nilai subskrip default untuk 'radius' pertama kali ditetapkan sebagai [35, 45, 78, 101] dan untuk 'Lingkaran' [90, 45, 56]] . Kemudian nilai subskrip diubah sebagai Radius [0] menjadi 78 dan Circle [1] menjadi 45.

Menautkan Beberapa Level Rangkaian

Beberapa sub kelas juga dapat ditautkan dengan metode kelas super, properti, dan langganan dengan rangkaian opsional.

Beberapa rangkaian opsional dapat dihubungkan -

Jika pengambilan jenis bukan opsional, rangkaian opsional akan mengembalikan nilai opsional. Misalnya jika String melalui rangkaian opsional, ia akan mengembalikan String? Nilai

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?

   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if let radiusName = circname.print?[0].radiusname {
   print("The first room name is \(radiusName).")
} else {
   print("Radius is not specified.")
}

Ketika kami menjalankan program di atas menggunakan playground, kami mendapatkan hasil sebagai berikut -

Radius is not specified.

Dalam program di atas, nilai instance untuk fungsi keanggotaan 'radiusName' tidak ditentukan. Oleh karena itu, panggilan program ke fungsi hanya akan mengembalikan bagian lain sedangkan untuk mengembalikan nilai kita harus menentukan nilai untuk fungsi keanggotaan tertentu.

Jika jenis pengambilan sudah opsional, rangkaian opsional juga akan mengembalikan nilai opsional. Misalnya jika String? Diakses melalui rangkaian opsional, ia akan mengembalikan String? Nilai..

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()

printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

if let radiusName = circname.print?[0].radiusname {
   print("Radius is measured in \(radiusName).")
} else {
   print("Radius is not specified.")
}

Ketika kami menjalankan program di atas menggunakan playground, kami mendapatkan hasil sebagai berikut -

Radius is measured in Units.

Dalam program di atas, nilai instance untuk fungsi keanggotaan 'radiusName' ditentukan. Karenanya, pemanggilan program ke fungsi sekarang akan mengembalikan nilai.

Merangkai Metode dengan Nilai Pengembalian Opsional

Rantai opsional juga digunakan untuk mengakses metode subclass yang ditentukan.

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("Area of Circle is: \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if circname.print?.circleprint() != nil {
   print("Area of circle is specified)")
} else {
   print("Area of circle is not specified")
}

Ketika kami menjalankan program di atas menggunakan playground, kami mendapatkan hasil sebagai berikut -

Area of circle is not specified