web-dev-qa-db-fra.com

Utilisation de Null/Nothing/Unit à Scala

Je viens de lire: http://oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/

Autant que je sache, Null est un trait et son seul exemple est null.

Lorsqu'une méthode prend un argument Null, nous pouvons uniquement lui passer directement une référence Null ou null, mais pas une autre référence, même si elle est nulle (nullString: String = null par exemple).

Je me demande simplement dans quels cas utiliser ce trait Null pourrait être utile ..__ Il y a aussi le trait Nothing pour lequel je ne vois pas vraiment plus d'exemples.


Je ne comprends pas vraiment non plus quelle est la différence entre utiliser Nothing et Unit en tant que type de retour, puisque les deux ne renvoient aucun résultat. Comment savoir lequel utiliser lorsque j'ai une méthode qui effectue la journalisation, par exemple?


Avez-vous des usages de Unit/Null/Nothing comme autre chose qu'un type de retour?

85
Sebastien Lorber

Vous utilisez uniquement Nothing si la méthode ne retourne jamais (ce qui signifie qu'elle ne peut pas se terminer normalement en renvoyant, elle pourrait générer une exception). Rien n'est jamais instancié et existe pour le système de types (pour citer James Iry: "La raison pour laquelle Scala a un type de fond est liée à sa capacité à exprimer la variance des paramètres de type." ). De l'article que vous avez lié à:

Une autre utilisation de Nothing est en tant que type de retour pour des méthodes qui n'ont jamais revenir. C'est logique si vous y réfléchissez. Si une méthode retourne le type est Nothing, et il n’existe absolument aucune instance de Nothing, alors une telle méthode ne doit jamais revenir.

Votre méthode de journalisation renverrait l'unité. Il existe une valeur Unité qui peut donc être renvoyée. A partir de la documentation API :

L'unité est un sous-type de scala.AnyVal. Il n'y a qu'une seule valeur de type Unit, (), et il n'est représenté par aucun objet dans le sous-jacent système d'exécution. Une méthode avec le type de retour Unit est analogue à Java méthode qui est déclarée nulle.

L'article que vous citez peut être trompeur. Le type Null existe pour la compatibilité avec la machine virtuelle Java , et Java en particulier.

Nous devons considérer que Scala :

  • est complètement orienté objet: chaque valeur est un objet
  • est fortement typé: chaque valeur doit avoir un type
  • doit gérer null références pour accéder, par exemple, aux bibliothèques Java et au code

il devient donc nécessaire de définir un type pour la valeur null, qui est le trait Null et dont null est l'unique instance.

Il n'y a rien de particulièrement utile dans le type Null sauf si vous êtes le système de types ou que vous développez sur le compilateur. En particulier, je ne vois aucune raison valable de définir un paramètre de type Null pour une méthode, car vous ne pouvez rien transmettre d'autre que null

16
pagoda_5b

Avez-vous des usages de Unit/Null/Nothing comme autre chose qu'un type de retour?


Unit peut être utilisé comme ceci:

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

Cela vous permet de transmettre un bloc de code arbitraire à exécuter.


Null peut être utilisé comme type de bas pour toute valeur pouvant être nullable. Voici un exemple:

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

Nothing est utilisé dans la définition de None

object None extends Option[Nothing]

Cela vous permet d'affecter une None à n'importe quel type de Option car Nothing 'étend' tout.

val x:Option[String] = None
15
EECOLOR

Je n'ai jamais réellement utilisé le type Null, mais vous utilisez Unit, où vous utiliseriez void sur Java. Nothing est un type spécial, car, comme Nathan l'a déjà mentionné, il ne peut y avoir d'instance de Nothing. Nothing est un type dit de bas, ce qui signifie qu'il s'agit d'un sous-type de tout autre type. Ceci (et le paramètre de type contravariant) explique pourquoi vous pouvez ajouter n'importe quelle valeur à Nil - qui est un List[Nothing] - et la liste sera alors de ce type d'éléments. None également si de type Option[Nothing]. Toute tentative d'accès aux valeurs à l'intérieur d'un tel conteneur lève une exception, car c'est le seul moyen valide de retourner à partir d'une méthode de type Nothing.

5
drexin

si vous utilisez Nothing, il n'y a rien à faire (incluez la console d'impression) si vous faites quelque chose, utilisez le type de sortie Unit

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

... alors comment utiliser Nothing?

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

Rien est souvent utilisé implicitement. Dans le code ci-dessous, val b: Boolean =if (1 > 2) falseelse throw new RuntimeException("error") La clause else est de type Nothing , qui est une sous-classe de Boolean (ainsi que tout autre AnyVal). Ainsi, toute l’affectation est valable pour le compilateur, bien que la clause else ne retourne rien.

3
Fang Zhang

Voici un exemple de Nothing à partir de scala.predef:

  def ??? : Nothing = throw new NotImplementedError

Si vous n'êtes pas familier (et que les moteurs de recherche ne peuvent pas y effectuer une recherche), ??? est la fonction d'espace réservé de Scala pour tout ce qui n'a pas encore été implémenté. Tout comme la variable TODO de Kotlin.

Vous pouvez utiliser le même truc lors de la création d'objets fantaisie: remplacez les méthodes inutilisées par une méthode notUsed personnalisée. L'avantage de ne pas utiliser ??? est que vous ne recevrez pas d'avertissement de compilation pour des choses que vous n'avez jamais l'intention de mettre en œuvre.

0
David Leppik

En termes de théorie des catégories, Nothing est un objet initial et Unit est un objet terminal.

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

Les objets initiaux sont également appelés coterminal ou universal et les objets terminaux sont également appelés final.

Si un objet est à la fois initial et terminal, il est appelé objet zero ou null.

0
Joe