Swift - İsteğe Bağlı Zincirleme
'Sıfır' olabilecek bir isteğe bağlı olarak sorgulama, özellikleri, alt simgeleri ve yöntemleri çağırma işlemi, isteğe bağlı zincirleme olarak tanımlanır. İsteğe bağlı zincirleme iki değer döndürür -
isteğe bağlı bir 'değer' içeriyorsa, ilgili özelliğini, yöntemlerini ve alt simgelerini çağırmak değerleri döndürür
isteğe bağlı bir 'nil' değeri içeriyorsa, tüm ilgili özelliği, yöntemleri ve alt simgeleri nil değerini döndürür
Yöntemlere, özelliklere ve alt simgelere yönelik birden çok sorgu birlikte gruplandırıldığından, tek bir zincirin başarısızlığı tüm zinciri etkileyecek ve "sıfır" değeriyle sonuçlanacaktır.
Zorla Açmaya Alternatif Olarak İsteğe Bağlı Zincirleme
İsteğe bağlı zincirleme, isteğe bağlı değerden sonra "?" isteğe bağlı değer bazı değerler döndürdüğünde bir özellik, yöntem veya alt simge çağırmak için.
İsteğe Bağlı Zincirleme '?' | Yöntemlere, özelliklere ve aboneliklere erişim İsteğe Bağlı Zincirleme '!' Açmayı zorlamak |
? özellik, yöntem veya indis çağırmak için isteğe bağlı değerden sonra gelir | ! değerin sarmalanmasını zorlamak için özellik, yöntem veya alt simge çağırmak için isteğe bağlı değerin arkasına yerleştirilir |
İsteğe bağlı "sıfır" olduğunda zarif bir şekilde başarısız olur | Zorla sarmalamadan çıkarma, isteğe bağlı "sıfır" olduğunda bir çalışma zamanı hatasını tetikler |
İsteğe Bağlı Zincirleme Programı '!'
class ElectionPoll {
var candidate: Pollbooth?
}
lass Pollbooth {
var name = "MP"
}
let cand = ElectionPoll()
let candname = cand.candidate!.name
Yukarıdaki programı oyun alanını kullanarak çalıştırdığımızda, aşağıdaki sonucu elde ederiz -
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
Yukarıdaki program, sınıf adı olarak 'seçim anketi'ni ilan eder ve üyelik işlevi olarak' aday'ı içerir. Alt sınıf, 'anket kabini' ve 'MP' olarak başlatılan üyelik işlevi olarak 'ad' olarak ilan edilir. Süper sınıfa yapılan çağrı, isteğe bağlı "!" İle bir "cand" örneği oluşturularak başlatılır. Değerler kendi temel sınıfında bildirilmediğinden, 'nil' değeri depolanır ve böylece sarmalamaya zorlama prosedürü ile ölümcül bir hata döndürür.
İsteğe Bağlı Zincirleme Programı '?'
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")
}
Yukarıdaki programı oyun alanını kullanarak çalıştırdığımızda, aşağıdaki sonucu elde ederiz -
Candidate name cannot be retreived
Yukarıdaki program, sınıf adı olarak 'seçim anketi'ni açıklar ve üyelik işlevi olarak' aday'ı içerir. Alt sınıf, 'anket kabini' ve 'MP' olarak başlatılan üyelik işlevi olarak 'ad' olarak ilan edilir. Süper sınıfa yapılan çağrı, isteğe bağlı "?" İle bir "cand" örneği oluşturularak başlatılır. Değerler kendi temel sınıfında bildirilmediğinden, 'nil' değeri konsolda saklanır ve else eylemci bloğu tarafından yazdırılır.
İsteğe Bağlı Zincirleme ve Özelliklere Erişim için Model Sınıflarını Tanımlama
Swift 4 dili, birden fazla alt sınıfı model sınıfları olarak bildirmek için isteğe bağlı zincirleme kavramını da sağlar. Bu kavram, karmaşık modelleri tanımlamak ve özelliklere, yöntemlere ve alt simge alt özelliklerine erişmek için çok yararlı olacaktır.
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")
}
Yukarıdaki programı oyun alanını kullanarak çalıştırdığımızda, aşağıdaki sonucu elde ederiz -
Rectangle Area is not specified
İsteğe Bağlı Zincirleme Yoluyla Yöntemleri Çağırma
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")
}
Yukarıdaki programı oyun alanını kullanarak çalıştırdığımızda, aşağıdaki sonucu elde ederiz -
Area of circle is not specified
Circle () alt sınıfında bildirilen circleprint () işlevi, 'circname' adlı bir örnek oluşturularak çağrılır. İşlev, bir değer içeriyorsa bir değer döndürür, aksi takdirde 'if circname.print? .Circleprint ()! = Nil' ifadesini kontrol ederek kullanıcı tanımlı bir yazdırma mesajı döndürür.
İsteğe Bağlı Zincirleme ile Aboneliklere Erişim
İsteğe bağlı zincirleme, o alt simgeye yapılan çağrının bir değer döndürüp döndürmediğini doğrulamak için bir alt simge değerini ayarlamak ve almak için kullanılır. '?' belirli bir alt simge üzerindeki isteğe bağlı değere erişmek için alt simge parantezlerinin önüne yerleştirilir.
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.")
}
Yukarıdaki programı oyun alanını kullanarak çalıştırdığımızda, aşağıdaki sonucu elde ederiz -
Radius is not specified.
Yukarıdaki programda 'radiusName' üyelik işlevi için örnek değerleri belirtilmemiştir. Dolayısıyla, işleve program çağrısı yalnızca başka bir bölümünü döndürür, oysa değerleri döndürmek için belirli üyelik işlevi için değerleri tanımlamamız gerekir.
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.")
}
Yukarıdaki programı oyun alanını kullanarak çalıştırdığımızda, aşağıdaki sonucu elde ederiz -
Radius is measured in Units.
Yukarıdaki programda, üyelik işlevi 'radiusName' için örnek değerleri belirtilmiştir. Bu nedenle işleve program çağrısı şimdi değerleri döndürecektir.
İsteğe Bağlı Türdeki Aboneliklere Erişim
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])
Yukarıdaki programı oyun alanını kullanarak çalıştırdığımızda, aşağıdaki sonucu elde ederiz -
Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)
Abonelikler için isteğe bağlı değerlere, alt simge değerlerine atıfta bulunularak erişilebilir. Alt simge [0], alt simge [1] vb. Olarak erişilebilir. "Yarıçap" için varsayılan alt simge değerleri ilk önce [35, 45, 78, 101] ve "Daire" [90, 45, 56]] olarak atanır. . Ardından alt simge değerleri Yarıçap [0] olarak 78 ve Daire [1] olarak 45 olarak değiştirilir.
Birden Fazla Zincirleme Düzeyini Bağlama
Birden fazla alt sınıf, isteğe bağlı zincirleme yoluyla süper sınıf yöntemleri, özellikleri ve alt simgeleriyle de bağlanabilir.
Çoklu isteğe bağlı zincirleme bağlanabilir -
Alma türü isteğe bağlı değilse, isteğe bağlı zincirleme isteğe bağlı bir değer döndürür. Örneğin, isteğe bağlı zincirleme yoluyla String varsa, String? Değer
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.")
}
Yukarıdaki programı oyun alanını kullanarak çalıştırdığımızda, aşağıdaki sonucu elde ederiz -
Radius is not specified.
Yukarıdaki programda, üyelik işlevi 'radiusName' için örnek değerleri belirtilmemiştir. Bu nedenle, fonksiyona yapılan program çağrısı yalnızca başka bir bölümünü döndürür, oysa değerleri döndürmek için belirli üyelik işlevi için değerleri tanımlamamız gerekir.
Geri alma türü zaten isteğe bağlıysa, isteğe bağlı zincirleme de isteğe bağlı bir değer döndürür. Örneğin eğer String? İsteğe bağlı zincirleme yoluyla erişilirse, String döndürür mü? Değer ..
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.")
}
Yukarıdaki programı oyun alanını kullanarak çalıştırdığımızda, aşağıdaki sonucu elde ederiz -
Radius is measured in Units.
Yukarıdaki programda, üyelik işlevi 'radiusName' için örnek değerleri belirtilmiştir. Bu nedenle, işleve program çağrısı şimdi değerleri döndürecektir.
İsteğe Bağlı Dönüş Değerlerine Sahip Yöntemlerde Zincirleme
İsteğe bağlı zincirleme, alt sınıf tanımlı yöntemlere erişmek için de kullanılır.
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")
}
Yukarıdaki programı oyun alanını kullanarak çalıştırdığımızda, aşağıdaki sonucu elde ederiz -
Area of circle is not specified