Scala에서 Null / Nothing / Unit 사용


95

방금 읽었습니다 : http://oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/

내가 이해 Null하는 한은 특성이고 유일한 인스턴스는 null.

메소드가 Null 인수를 받으면 Null참조 또는 null직접 전달 만 할 수 있지만 null 인 경우에도 다른 참조 는 전달할 수 없습니다 ( nullString: String = null예 :).

Null특성을 사용하는 것이 어떤 경우에 유용 할 수 있는지 궁금 합니다. 더 이상 예를 볼 수없는 Nothing 특성도 있습니다.


둘 다 어떤 결과도 반환하지 않기 때문에 Nothing과 Unit을 반환 유형으로 사용하는 것의 차이점이 무엇인지 실제로 이해하지 못합니다.


Unit / Null / Nothing을 반환 유형 이외의 것으로 사용하고 있습니까?

답변:


80

메서드가 반환되지 않는 경우에만 Nothing을 사용합니다 (즉, 반환하여 정상적으로 완료 할 수 없으며 예외가 발생할 수 있음). 어떤 것도 인스턴스화되지 않으며 유형 시스템의 이점을 위해 존재합니다 (James Iry를 인용하기 위해 : "Scala가 최하위 유형을 갖는 이유는 유형 매개 변수의 분산을 표현하는 능력과 관련이 있습니다." ). 링크 한 기사에서 :

Nothing의 또 다른 용도는 반환하지 않는 메서드에 대한 반환 유형입니다. 생각해 보면 말이됩니다. 메서드의 반환 유형이 Nothing이고 Nothing의 인스턴스가 전혀 존재하지 않는 경우 이러한 메서드는 반환되지 않아야합니다.

로깅 방법은 Unit을 반환합니다. 실제로 반환 될 수 있도록 단위 값이 있습니다. 로부터 API 문서 :

단위는 scala.AnyVal의 하위 유형입니다. Unit 유형 (())의 값은 하나만 있으며 기본 런타임 시스템의 객체로 표현되지 않습니다. 리턴 유형이 Unit 인 메소드는 void로 선언 된 Java 메소드와 유사합니다.


2
감사합니다. "반환하지 않음"은 호출이 무기한 차단된다는 의미입니까 (예 : 작업 스케줄러의 시작 방법?)
Sebastien Lorber

3
@Sabastien : 정상적으로 반환되지 않고 예외가 발생할 수 있습니다 ( james-iry.blogspot.com/2009/08/… 참조 ). 차단 호출이 예외 발생으로 만 종료되면 계산됩니다. 질문에 감사드립니다. 이것은 명확히해야합니다.
Nathan Hughes

18

인용 한 기사는 오해의 소지가 있습니다. Null유형과의 호환성을 위해이 자바 가상 머신 , 특히 자바.

우리는 Scala 를 고려해야합니다 .

  • 완전히 객체 지향적입니다. 모든 값은 객체입니다.
  • 강력한 유형 : 모든 값에는 유형이 있어야합니다.
  • null액세스에 대한 참조 (예 : Java 라이브러리 및 코드) 를 처리해야합니다.

따라서 특성 인 null값에 대한 유형을 정의 할 필요가 있으며 유일한 인스턴스가됩니다.Nullnull

Null유형 시스템이 아니거나 컴파일러에서 개발하지 않는 한 유형 에서 특별히 유용한 것은 없습니다 . 특히 Null메서드에 대한 형식 매개 변수 를 정의하는 합리적인 이유를 볼 수 없습니다.null


그것은 사실입니다. 그래서 결국 Null의 다른 사용법은 없습니까?
Sebastien Lorber 2013

@SebastienLorber가 대답을 편집했습니다. 실제로 일반 개발자의 사용량을 볼 수 없습니다. 다른 누군가가 유용한 것을 생각할 수 있습니다.
pagoda_5b 2013

감사합니다. 이런 종류의 이유를 알면 이해하고 그렇지 않으면 기억합니다.
Sreekar

Null은 유형 매개 변수 가 있고이 질문과 답변 에서처럼 null을 반환하고 싶을 때 유용합니다 . 스칼라에서 null을 사용하지 않는 것이 좋지 않기 때문에 거의 나타나지 않지만 유형 시스템에서도 다른 용도가있을 수 있습니다
Daniel Carlsson

15

Unit / Null / Nothing을 반환 유형 이외의 것으로 사용하고 있습니까?


Unit 다음과 같이 사용할 수 있습니다.

def execute(code: => Unit):Unit = {
  // do something before
  code
  // do something after
}

이를 통해 실행될 임의의 코드 블록을 전달할 수 있습니다.


Nullnullable 값에 대한 하단 유형으로 사용될 수 있습니다. 예는 다음과 같습니다.

implicit def zeroNull[B >: Null] =
    new Zero[B] { def apply = null }

Nothing 정의에 사용됩니다. None

object None extends Option[Nothing]

이를 통해 None모든 유형을 '확장' Option하기 때문에 모든 유형 에을 할당 할 수 있습니다 Nothing.

val x:Option[String] = None

확인. Unit 사용을 위해 코드 블록이 unit 이외의 것을 반환하는 경우 실행이이 일반 유형을 반환 할 수 있도록 일반 유형을 사용할 수 있습니다.
Sebastien Lorber 2013

@drexin이 다른 답변에 대한 의견에서 말했듯이 대부분 부작용을 나타내는 데 사용됩니다.
EECOLOR 2013-04-23

6

를 사용하면 할 Nothing일이 없습니다 (인쇄 콘솔 포함) 뭔가를하면 출력 유형을 사용하십시오Unit

object Run extends App {
  //def sayHello(): Nothing = println("hello?")
  def sayHello(): Unit = println("hello?")
  sayHello()
}

... 어떻게 사용 Nothing합니까?

trait Option[E]
case class Some[E](value: E) extends Option[E]
case object None extends Option[Nothing]

1
또한 Ein은 Option공변 적 위치에 있어야합니다. 다음 trait Option[+E]과 같은 것을 허용하려면val x: Option[Int] = None
vim

5

나는 실제로 Null유형을 사용한 적이 없지만 UnitJava에서 사용하는 void. NothingNathan이 이미 언급했듯이의 인스턴스가있을 수 없기 때문에 특수 유형입니다 Nothing. Nothing이것은 다른 유형의 하위 유형임을 의미하는 소위 하단 유형입니다. 이것이 (및 반 변성 유형 매개 변수) Nil- 앞에 값을 추가 할 수있는 이유 입니다. 즉 List[Nothing], 목록은이 요소 유형이됩니다. None또한 유형 Option[Nothing]. 이러한 컨테이너 내부의 값에 액세스하려고 할 때마다 예외가 발생합니다 Nothing. 유형의 메서드에서 반환하는 유일한 유효한 방법이기 때문입니다 .


감사합니다. None이 Option [Nothing]을 확장한다는 것을 몰랐습니다. 하위 유형이 Nothing을 사용할 수있는 일부 제네릭 사용에서 의미가 있습니다 (Null 및 Unit에 대한 예제를 찾기가 어렵습니다 ...)
Sebastien Lorber 2013-04-23

예를 들어 IO 모나드는 IO[Unit]콘솔에 인쇄하기위한 유형일 수 있습니다 .
drexin 2013

예, IO 모나드를 사용한 적이 없습니다. Unit과 함께 사용하는 것이 합리적입니다 (무한 스트림을 생성하는 일부 IO 작업 인 경우에는 아무 것도 없습니까?)
Sebastien Lorber

아니, 아무것도 말이 안 돼.
drexin 2013

3

암시 적으로 자주 사용되는 것은 없습니다 . 아래 코드 val b: Boolean = if (1 > 2) false else throw new RuntimeException("error") 에서 else 절은 Nothing 유형 이며, 이는 Boolean (및 기타 AnyVal)의 하위 클래스입니다. 따라서 else 절이 실제로 아무것도 반환하지 않더라도 전체 할당이 컴파일러에 유효합니다 .


1

다음은 Nothingfrom 의 예입니다 scala.predef.

  def ??? : Nothing = throw new NotImplementedError

익숙하지 않은 경우 (검색 엔진에서 검색 할 수없는 경우) ???아직 구현되지 않은 항목에 대한 Scala의 자리 표시 자 기능이 있습니다. Kotlin의 TODO.

모의 객체를 생성 할 때 동일한 트릭을 사용할 수 있습니다. 사용하지 않는 메서드를 사용자 지정 notUsed메서드로 재정의 합니다. 사용하지 않을 때의 장점은 ???구현할 의도가없는 것에 대해 컴파일 경고를받지 않는다는 것입니다.


0

카테고리 이론의 관점에서 아무것도 이다 초기 개체단위 A는 터미널 객체 .

https://en.wikipedia.org/wiki/Initial_and_terminal_objects

초기 객체coterminal 또는 universal 이라고도 하며 터미널 객체final 이라고도 합니다.

객체가 initialterminal 모두 인 경우 0 객체 또는 null 객체 라고 합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.