-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
<4주차> Optional 이란 무엇인지 설명하시오. #22
Comments
Optional래핑된 값 또는 값이 없는 nil 상태를 표현하는 형식이며, enum 구조를 뛰고 있다. Optional.none은 nil과 동일하다 공식문서 예시 코드 let number: Int? = Optional.some(42)
let noNumber: Int? = Optional.none 여러 컨텍스트에서 Optional 값을 사용하려면 Optional 인스턴스의 값을 래핑을 해제한 후 사용해야 합니다. 래핑된 값을 새 변수에서 바인딩 하려면 if let과 guard let 그리고 switch문을 이용해 옵셔널 바인딩을 할 수 있습니다. if let starPath = imagePaths["star"] {
print("The star image is at '\(starPath)'")
} else {
print("Couldn't find the star image")
} 강제 옵셔널로 값을 사용할 수 있지만, 프로젝트 크기가 커지고 협업을 하다보면 예상치 못하게 앱이 let number = Int("42")!
print(number)
// Prints "42" |
Optional이란? |
Optionalnil을 사용할 수 있는 타입과 사용할 수 없는 타입을 구분하고, 사용할 수 있는 타입을 가리켜 옵셔널 타입이라고 부른다.
옵셔널 타입으로 선언된 자료형은 nil 값을 저장할 수 있다. 옵셔널 언래핑 (Optional Unwrapping)
|
OptioanalSwift의 Fast, Safe, Expression 의 특징 중 Safe를 가장 잘 보장해줄 수 있는 기능. 그렇기 때문에 Optional 값을 사용하기 위해선 값이 있는지 없는지 확인하는 작업이 필요하다. 첫번째로 '!'을 사용해서 강제 Unwrapping을 실행할 수 있다. 그러나 이 방법은 런타임 중에 에러를 발생시킬 수 있기 때문에 정말 값이 없다고 보장하는 경우에만 사용하는 것이 권장! 두번째는 Optional Binding을 이용하는 방법이 있다. if var, if let, guard let 구문과 함께 사용해서 더욱 안전하게 Unwrapping을 할 수 있다. Optional에서 추가로 공부하면 좋을 것은 |
Optionalswift 에서는 변수를 선언할 때 non-optional 한 값을 변수에 주어야 합니다. 만일 변수 안에 값이 확실히 있다는 것을 보장할 수 없으면 Optional 을 사용해야 합니다. 타입 어노테이션 값에 Optional 기호 var test: Int? optional 변수는 초기화 하지 않으면 nil 로 자동으로 초기화 됩니다. Optional 변수의 값 가져오는 방법
옵셔널에 값이 있다고 가정하고 값에 바로 접근할 수 있도록 강제하는 방법입니다. 느낌표(!) 키워드를 붙여 사용합니다. 그러나 값이 존재하지 않는 옵셔널 값에 접근하려 시도하면 런타임 에러가 발생합니다. 느낌표를 사용하여 강제 언래핑 하기 전에 항상 옵셔널 값이 nil 이 아니라는 것을 확실히 해야 합니다. var optionalEmail: String?
print(optionalEmail!)
가급적이면 일반적인 옵셔널을 사용해서 정의하고, 옵셔널 바인딩 또는 옵셔널 체이닝을 통해 값에 접근하는 것이 더 바람직합니다.
옵셔널의 값이 존재하는 지를 검사한 뒤, 존재한다면 그 값을 다른 변수에 대입시켜줍니다. if let email = optionalEmail {
print(email)
} var optionalAge: Int? = 22
if let age = optionalAge, age >= 20 {
print(age)
}
옵셔널 체이닝은 옵셔널의 속성에 접근할 때, 옵셔널 바인딩 과정을
|
Optionalref : https://www.youtube.com/watch?v=25dvsEiwn4s&feature=youtu.be&t=824
위에 사용법들은 너무 많이 잘 적어줘서 조금 줄이고( IUO, 강제 언래핑 등),,,, 모나드 이야기를 하겟읍니다 Monad설명을 위해 Content와 Context 맥락을 도입합니다. (Content == Container) Optional을 다루고 난 데이터는 Optional을 리턴합니다. 다음을 봅시다. 딕셔너리는 대표적으로 Optional을 리턴하는 객체입니다. 그 다음줄에서 data에 확실한 인티저 3을 대입해주었을 때 정답은 X입니다. data의 Optional 타입은 바뀌지 않습니다. 이유는 다음 코드로 설명을 해보겠습니다, Monad를 코드로 써 볼게요. class Functer<T> {
let value: T
init(_ v: T) {
value = v
}
func map<U>(_ f: (T) -> U) -> Functer<U> {
let u = f(value)
return Functer<U>(u)
}
} 다음과 같은 Functer class가 있고, 내부함수 map함수는 Functer를 리턴하고 있습니다. let name = "Original"
let changeNameLength = Functer(name) // Funter<String>
.map { "\($0) Changed" } // Funter<String>
.map { $0.count } // Funter<Int>
.map { $0 * $0 } // Funter<Int>
.value
print(changeNameLength) Functer 클래스 내부함수에서 map은 Functer를 리턴하니 계속 map을 활용할 수 있습니다. 옵셔널도 위와 같은 컨테이너 역할을 하게 됩니다. 그럼, 그런데 얘내들은 문제가 생기죠...어떤 문제냐면, 제가 이제 함수를 만들어 볼게요. 그리고 다른 함수, Functer를 리턴해주는 함수를 만들어 볼거에요. func stringLength(_ s: String) -> Functer<Int> {
return Functer(s).map { $0.count }
} 스트링 길이를 구하는 함수를 만들었습니다. let changeNameLength = Functer(name) // Funter<String>
.map { "\($0) Changed" } // Funter<String>
.map (stringLength) // Functer<Funter<String>> ㅏㅏ Error
.map { $0 * $0) //
.value
print(changeNameLength) 이렇게 사용하면 다음과 같은 문제가 생깁니다. Functer Class에 flatMap을 만들어 봅시다. class Functer<T> {
let value: T
init(_ v: T) {
value = v
}
func map<U>(_ f: (T) -> U) -> Functer<U> {
let u = f(value)
return Functer<U>(u)
}
func flatMap<U>(_ f: (T) -> Functer<U>) -> Functer<U> {
let fu = f(value)
return Functer<U>(fu.value)
}
} flatMap은 Functer를 리턴하는 인자 f를 받아서 value를 추출한다음, 다시 Functer를 리턴해주니까 let changeNameLength = Functer(name) // Funter<String>
.map { "\($0) Changed" } // Funter<String>
.flatMap(stringLength(_:)) // Funter<Int>
.map { $0 * $0 } // Funter<Int>
.value
print(changeNameLength) 이 코드도 문제없이 동작하게 됩니다. Immutable Data를 다루는 관점Optional 안에 있는 값의 관점에서 보면, 위에서 보았듯 Optional이라는 것으로 Wrapping되어 있으므로 이를 바로 수정할 수 없습니다.
위와 같은 세가지의 장점을 가질 수 있습니다. 그림으로 마무리 해보겠습니다. 변경된 값이 필요하다? 새로 만들어라! 가 핵심이 되겠습니다. |
OptionalOptional 이란 값이 있을 수도 있고 없을 수도 있다는 뜻을 나타내는 개념으로 일반적인 자료형 옆에 '?' 표시를 해줌으로 표현할 수 있다. 그리고 '?'로 표시된 옵셔널 타입의 변수는 'Optional<>'이라는 객체로 쌓여져 있게 된다. 따라서 이러한 변수를 사용하기 위해서는 unwrapping 과정이 필요하다. Unwrapping을 하는 방법에는 강제추출, 옵셔널 바인딩, 옵셔널 체이닝 이 있다. 강제 추출의 경우 nilsafe하지 않고 Optional로 Wrapping된 객체를 강제로 뜯어서 사용하는 방법이다. 따라서 컴파일 단계에서는 문제가 안나타날 수 있으나 만약 런타임에서 강제추출로 접근한 변수에 nil이 할당되어 있다면 런타임 에러가 발생할 것이다. 옵셔널 바인딩의 경우 if let 구문, guard let 구문 으로 옵셔널 타입 변수에 대한 에러 핸들링이 가능하도록 해주는 문법 이다. Unwrapping 할 옵셔널 변수에 실제 nil 이 할당되어 있다면 ,else 문을 통해 에러를 처리해 줄 수 있도록 해준다. 이 둘의 차이는 옵셔널 Unwrapping단계를 통해 할당 된 변수의 Scope의 차이가 있다. if let 의 경우 { } 내부에 할당 된 지역변수로만 사용되고 나머지에선 사용할 수 없다. guard let의 경우에는 자신이 위치 한 블록 내에서 전부 사용할 수 있도록 해주는 차이가 있다. |
옵셔널이란 갑이 있을수도 있고 없을수도있다는 것을 표현해주는 개념!!*** 보다가 배운것 Objc에서는 옵셔널이 필수였는데 swift에서는 선택적인 개념이 되었다는 것?? var number: Int? = 20 이라고 하면 20으로 선언된 변수이지만 나중에 언제든지 nil로 변경이 될수있다는 점!! 그리고 해당 변수를 사용하기 위해서는 옵셔널 바인딩 처리를 해 사용을 해야한다는 점!! guard let nonOptionalNumber = number else { return } // number를 nonOptionalNumber로 사용 가능
if let nonOptionalNumber = number {
// 이 스코프에서 number를 nonOptionalNumber로 사용 가능
} |
No description provided.
The text was updated successfully, but these errors were encountered: