Scala Language
옵션 클래스
수색…
통사론
class [+ T] (value : T)는 Option [T]를 확장합니다.
객체 없음 확장 옵션 [아무것도]
옵션 [T] (값 : T)
제공된 값에 대해
Some(value)
또는None
을 생성하는 생성자.
컬렉션 옵션
Option
에는 0 또는 하나의 항목이있는 컬렉션으로 옵션을 보면 쉽게 이해할 수있는 유용한 고차 함수가 있습니다. None
은 빈 컬렉션처럼 동작하고 Some(x)
는 단일 항목 x
있는 컬렉션처럼 동작합니다.
val option: Option[String] = ???
option.map(_.trim) // None if option is None, Some(s.trim) if Some(s)
option.foreach(println) // prints the string if it exists, does nothing otherwise
option.forall(_.length > 4) // true if None or if Some(s) and s.length > 4
option.exists(_.length > 4) // true if Some(s) and s.length > 4
option.toList // returns an actual list
Null 대신 Option 사용
Java (및 다른 언어)에서 null
사용하는 것은 참조 변수에 값이 첨부되지 않았 음을 나타내는 일반적인 방법입니다. 스칼라에서는 null
을 사용하는 것보다 Option
을 사용하는 것을 선호합니다. Option
은 null
일 수 있는 값을 래핑합니다.
None
은 null 참조를 래핑하는 Option
의 서브 클래스입니다. Some
는 null이 아닌 참조를 래핑하는 Option
서브 클래스입니다.
참조 래핑은 쉽습니다.
val nothing = Option(null) // None
val something = Option("Aren't options cool?") // Some("Aren't options cool?")
null 참조를 반환하는 Java 라이브러리를 호출 할 때 일반적인 코드입니다.
val resource = Option(JavaLib.getResource())
// if null, then resource = None
// else resource = Some(resource)
getResource()
가 null
값을 반환하면 resource
은 None
객체가됩니다. 그렇지 않으면 Some(resource)
객체가됩니다. Option
을 처리하는 가장 좋은 방법은 Option
유형 내에서 사용할 수있는 고차 함수를 사용하는 것입니다. 예를 들어 값이 None
이 아닌지 확인하려면 value == null
인지 확인하는 것과 유사하게 isDefined
함수를 사용합니다.
val resource: Option[Resource] = Option(JavaLib.getResource())
if (resource.isDefined) { // resource is `Some(_)` type
val r: Resource = resource.get
r.connect()
}
마찬가지로 null
참조를 확인하려면 다음을 수행 할 수 있습니다.
val resource: Option[Resource] = Option(JavaLib.getResource())
if (resource.isEmpty) { // resource is `None` type.
System.out.println("Resource is empty! Cannot connect.")
}
Option
을 모나드로 취급하고 foreach
를 사용하여 Option
( '예외' Option.get
메소드를 사용하지 않고)의 래핑 된 값에 대한 조건부 실행을 처리하는 것이 바람직합니다.
val resource: Option[Resource] = Option(JavaLib.getResource())
resource foreach (r => r.connect())
// if r is defined, then r.connect() is run
// if r is empty, then it does nothing
Resource
인스턴스가 필요한 경우 ( Option[Resource]
인스턴스와 비교하여) Null 값을 방지하기 위해 Option
을 계속 사용할 수 있습니다. 여기서 getOrElse
메소드는 기본값을 제공합니다.
lazy val defaultResource = new Resource()
val resource: Resource = Option(JavaLib.getResource()).getOrElse(defaultResource)
자바 코드는 쉽게 스칼라의 처리하지 않습니다 Option
, 그래서 자바 코드에 값을 전달할 때 푸는 좋은 형태의 Option
전달 null
또는 재치있는 기본 적절한를 :
val resource: Option[Resource] = ???
JavaLib.sendResource(resource.orNull)
JavaLib.sendResource(resource.getOrElse(defaultResource)) //
기초
Option
은 단일 값 또는 전혀 값이없는 데이터 구조입니다. Option
은 0 개 또는 하나의 요소로 이루어진 콜렉션으로 생각할 수 있습니다.
Option은 두 개의 자식이있는 추상 클래스입니다 : Some
과 None
.
Some
는 단일 값을 포함하고 None
은 값을 포함하지 않습니다.
Option
은 특정 값의 부족을 나타 내기 위해 null
을 사용하는 식에서 유용합니다. 이는 NullPointerException
방지하고 Map
, FlatMap
등과 같은 연결자를 사용하여 값을 반환하지 않는 많은 표현식을 허용합니다.
지도가있는 예
val countries = Map(
"USA" -> "Washington",
"UK" -> "London",
"Germany" -> "Berlin",
"Netherlands" -> "Amsterdam",
"Japan" -> "Tokyo"
)
println(countries.get("USA")) // Some(Washington)
println(countries.get("France")) // None
println(countries.get("USA").get) // Washington
println(countries.get("France").get) // Error: NoSuchElementException
println(countries.get("USA").getOrElse("Nope")) // Washington
println(countries.get("France").getOrElse("Nope")) // Nope
Option[A]
가 봉인 되었으므로 확장 할 수 없습니다. 따라서 의미가 안정적이며 신뢰할 수 있습니다.
이해를위한 옵션
Option
에는 flatMap
메서드가 있습니다. 이것은 그들이 이해를 위해 사용될 수 있음을 의미합니다. 이 방법으로 우리는 다시 정의하지 않고도 Option
에서 작업 할 수있는 정규 함수를들 수 있습니다.
val firstOption: Option[Int] = Option(1)
val secondOption: Option[Int] = Option(2)
val myResult = for {
firstValue <- firstOption
secondValue <- secondOption
} yield firstValue + secondValue
// myResult: Option[Int] = Some(3)
값 중 하나가 None
이면 계산의 종료 결과는 None
됩니다.
val firstOption: Option[Int] = Option(1)
val secondOption: Option[Int] = None
val myResult = for {
firstValue <- firstOption
secondValue <- secondOption
} yield firstValue + secondValue
// myResult: Option[Int] = None
주 :이 패턴은 Monad
라 불리는 개념에 대해보다 일반적으로 확장됩니다. (더 많은 정보는 이해 및 Monad
와 관련된 페이지에서 이용 가능해야합니다)
일반적으로 서로 다른 모나드를 섞어서 이해하는 것은 불가능합니다. 그러나 Option
은 쉽게 Iterable
변환 될 수 있기 때문에 .toIterable
메소드를 호출하여 Option
과 Iterable
쉽게 혼합 할 수 있습니다.
val option: Option[Int] = Option(1)
val iterable: Iterable[Int] = Iterable(2, 3, 4, 5)
// does NOT compile since we cannot mix Monads in a for comprehension
// val myResult = for {
// optionValue <- option
// iterableValue <- iterable
//} yield optionValue + iterableValue
// It does compile when adding a .toIterable on the option
val myResult = for {
optionValue <- option.toIterable
iterableValue <- iterable
} yield optionValue + iterableValue
// myResult: Iterable[Int] = List(2, 3, 4, 5)
작은 메모 : 만약 우리가 우리의 이해를 정의했다면 우리의 선택이 암묵적으로 변환 될 것이기 때문에 이해를 둘러싼 다른 방법이 컴파일 될 것입니다. 이런 이유로 .toIterable
을 위해 항상 .toIterable
(또는 사용하는 컬렉션에 따라 해당 함수)을 추가하는 것이 유용합니다.