수색…


통사론

  • 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 값을 반환하면 resourceNone 객체가됩니다. 그렇지 않으면 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은 두 개의 자식이있는 추상 클래스입니다 : SomeNone .

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 메소드를 호출하여 OptionIterable 쉽게 혼합 할 수 있습니다.

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 (또는 사용하는 컬렉션에 따라 해당 함수)을 추가하는 것이 유용합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow