15.光学鎖


光学フィルタリングは、nilの現在の光学構成、メソッド、サブスクリプトをクエリーおよび呼び出すプロセスです.傍観者が値を持つ場合、propertyやメソッドなどが正常に呼び出されます.ただし、傍観者がnilの場合、property、メソッド、サブスクリプト呼び出しはnilを返します.複数のクエリーを1行に接続できます.チェーンの任意の部分がnilの場合、チェーン全体が失敗します.

強制反転代替案としてのギャップ

  • 参照フィルタは、クエリのProperty、メソッド、およびサブスクリプトが非参照値の値を返しても、nil値を呼び出すことができる事実を反映して、常に参照され、返されます.
  • class Person {
    	var residence : Residence?
    }
    
    class Residence {
    	var numberOfRooms = 1
    
    }
    
    let john = person()
    //현재 존은 nil의 residence 프로퍼티 값을 가지고 있다.
    //아래서는 이에 대해 강제 언래핑을 시도하는 코드를 작성한다
    let roomCount = john.residence!.numberOfRooms
    //다음과 같을 시 에러가 난다. 왜냐면 레지던스 값이 nil로 없는 상태이기 때문이다.
    
    if let roomCount = john.residence?.numberOfRooms {
    	print(roomCount)
    } else {
    	print("unable to retrieve roomCount")
    }
    //옵셔널 체이닝은 numberOfRoom에 접근하기 위한 대안으로 제공된다. 체이닝을 위해서 느낌표 위에 물음표를 사용해준다.
    //이것은 옵셔널 residence 프로퍼티를 "체인" 하고 residence가 존재 시 numberOfRooms 값을 조회하도록 설정한 것이다.

    サブアクセス光学体のモデルクラスの定義とサブアクセス

  • タイプの互換性のある複雑なモデルでサブPropertyに降格したり、サブProperty、メソッド、サブスクリプトにアクセスできるかどうかを決定したりできます.
  • class Person {
    	var residence : Residence?
    }
    
    class Residence {
    	var rooms : [Room] = []
        var numberOfRooms : Int {
        	return rooms.count
        }
        
        func printNumberOfRooms() {
        	print(numberOfRooms)
        }
        
        var address : Address?
    }
    
    class Room {
    	let name : String
        init(name : String) {
        	self.name = name
        }
    }
    
    class Address {
    	var building : String?
        var buildingNumber : String?
        var street : String?
        
        func buildingIdentifier() -> String? {
        	if let number = buildingNumber, let street = street {
            	return "\(number), \(street)"
            else {
            	return nil
            }
        }
    }
    
    //다음과 같이 각 옵셔널 인스턴스를 포함하는 4개의 클래스를 정의하였다.
    //아래에서는 옵셔널 체이닝을 통해 프로퍼티에 접근해본다.
    
    let john = Person()
    
    if let roomCount = john.residence?.numberOfRooms {
    	print("nice!")
    } else {
    	print("unable to do that")
    }
    //다음에서 john의 residence는 현재 nil로 초기화 되어있으므로 nil을 리턴하여 else를 수행하게 된다.
    
    let someAddress = Address()
    someAddress.buildingNumber = "29"
    someAddress.street = "Acacia Road"
    john.residence?.address = someAddress
    //여기에서는 아직 john의 residence가 nil이기 때문에 address에 접근하기 위한 시도는 에러가 난다.
    
    
    if john.residence?.printNumberOfRooms() != nil {
    	print("possible to print")
    } else {
    	print("impossible to print")
    }
    //다음과 같이 옵셔널 체이닝을 통해서 메서드에도 접근이 가능하며, 체이닝 결과에 따라서 흐름제어가 가능하다.
    
    if let firstRoomName = john.residence?[0].name {
    	print(firstRoomName)
    } else {
    	print("no name!")
    }
    //다음과 같이 서브스크립트에도 접근이 가능하다. 지금은 residence 인스턴스가 가지는 배열의 값에 대해 
    //index를 통해 접근하는 시도를 하고 있고, 
    //이 또한 만약 residence가 nil인 경우 전체 nil을 반환하여 호출은 실패한다.

    複数のステップをカスケードする外部チェーン

  • の複数のフェーズのオープン・フィルタを使用すると、モデル内で各Property、メソッド、サブスクリプトに深くアクセスできます.この時点でクエリーするタイプがオフセット量でない場合、オフセット量はオフセット値を返します.クエリーのタイプが古い場合は、フィルタリングのためにより多くの傍観者になることはありません.傍観者になるだけだ.
  • if let johnStreet = john.residence?.address?.street {
    	print(johnStreet)
    } else {
    	print("unable to do that")
    }
    //다음과 같이 2중 옵셔널 체이닝이 가능하며, 단계적으로 옵셔널 여부를 체크하며
    //코드를 전개할 수 있다.

    オフセット戻り値のオフセット

  • 傍観者フィルタはまた、必要に応じてメソッド戻り値を接続する傍観者タイプ値を返す方法を呼び出すこともできる.
  • if let buildingIdentifier` = john.residence?.address?.buildingIdentifier() {
    	print(buildingIdentifier)
    } else {
    	print("can't")
    }