[Scala基础]--Null、null、 Nothing、 Nil、 None和Unit

Scala 专栏收录该内容
68 篇文章 2 订阅

原文:

http://oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/

您听到的有关Scala语言的主要抱怨之一是与Java相比,它太复杂了。一般的开发者永远无法对类型系统,函数式编程语言等有足够的理解。这就是论点。为了支持这个位置,你会经常听到它指出Scala包含了一些虚无的概念(Null,null,Nil,Nothing,None和Unit),并且你必须知道在不同情况下使用哪一个。我不止一次读过这样的论点。

这不是那么糟糕。是的,这些都是Scala的一部分,是的,你必须在正确的情况下使用正确的。但情况如此千差万别,一旦你知道这些事情是什么意思,就不难了解了。

Null and null

首先,我们来处理Null和null。空(Null)是一个trait,它(如果你不熟悉trait)有点像Java中的抽象类。确实存在一个空的实例,那是空的。不那么难 字面null与Java中的相同。它是不引用任何对象的引用的值。因此,如果您编写一个采用Null类型参数的方法,则只能传递两个值:null本身或Null类型的引用。
注意:

 
scala> def tryit(thing: Null): Unit = { println("That worked!"); }
tryit: (Null)Unit

scala> tryit("hey")
<console>:6: error: type mismatch;
 found   : java.lang.String("hey")
 required: Null
       tryit("hey")
             ^

scala> val someRef: String = null
someRef: String = null

scala> tryit(someRef)
<console>:7: error: type mismatch;
 found   : String
 required: Null
       tryit(someRef)
             ^

scala> tryit(null)
That worked!

scala> val nullRef: Null = null
nullRef: Null = null

scala> tryit(nullRef)
That worked!

Nil

Nil是一个容易的。Nil是扩展List [Nothing]的对象(下面我们将讨论Nothing)。这是一个空的列表。以下是使用Nil的一些示例代码:
scala> Nil
res4: Nil.type = List()

scala> Nil.length
res5: Int = 0

scala> Nil + "ABC"
res6: List[java.lang.String] = List(ABC)

scala> Nil + Nil
res7: List[object Nil] = List(List())

能看到? 它基本上是一个不断封装任何东西的空列表。 这是零长度。 它根本不代表“虚无”。 这是一个名单,一个List。 没有内容。

Nothing

如果其中任何一个有点难以得到,那就什么都不是。Nothing是另一个trait。它继承了Any类。Any是整个Scala类型系统的超类Any可以引用对象类型以及诸如普通的旧整数或双精度的值。没有Nothing的例子,但是(这里是棘手的一点)Nothing是一切类的子类  Nothing是List的子类,它是String的子类,它是Int的子类型,它是YourOwnCustomClass的子类。

还记得Nil吗?这是一个List [Nothing],它是空的。由于Nothing是一切类的子类,所以Nil可以被用作一个空的字符串列表,一个空的Ints列表,一个空的Any列表。所以没有什么是有用的定义集合或其他类采取类型参数的基本情况。这里是一个scala会话的片段:

scala> val emptyStringList: List[String] = List[Nothing]()
emptyStringList: List[String] = List()

scala> val emptyIntList: List[Int] = List[Nothing]()
emptyIntList: List[Int] = List()

scala> val emptyStringList: List[String] = List[Nothing]("abc")
<console>:4: error: type mismatch;
 found   : java.lang.String("abc")
 required: Nothing
       val emptyStringList: List[String] = List[Nothing]("abc")

在第1行,我们将一个List [Nothing]分配给对List [String]的引用。Nothing是字符串,所以它正常工作。在第4行,我们将一个List [Nothing]赋值给List [Int]的引用。Nothing也是一个Int,所以这也是一样的。Nothing是一切类的子类。但是这两个List [Nothing]实例都不包含成员。当我们尝试创建一个List [Nothing]包含一个String并将该List分配给一个List [String]引用时会发生什么?它失败了,因为虽然Nothing是所有东西的子类,但它不是任何东西的超类,也 没有 Nothing的实例,包括字符串“abc”。所以Nothing的任何集合都必须是空的。

Nothing的另一个用途是作为永不  返回的方法的返回类型  如果你仔细想想,这是有道理的。如果方法的返回类型是Nothing,并且绝对不存在Nothing的实例,那么这样的方法不能返回。

None

当你用Java写一个函数,遇到你没有什么实用价值的情况时,你会怎么做?有几种方法来处理它。你可以返回null,但是这会导致问题。如果调用者不希望得到null,那么当他尝试使用它时可能会面临NullPointerException,否则调用者必须检查null。一些函数肯定不会返回null,但有些函数可能会。作为一个调用者,你不知道。

有一种方法可以在函数签名中声明,你可能无法返回一个很好的值,throws关键字。但是try / catch块有一个相关的成本,而且你通常希望保留异常情况下的使用,而不仅仅是为了表示一个普通的无结果的情况。

Scala有这个问题的内置解决方案。例如,如果你想返回一个字符串,但你知道你可能无法返回一个合理的值,你可以返回一个Option[String]。这是一个简单的例子。

scala> def getAStringMaybe(num: Int): Option[String] = {
     |   if ( num >= 0 ) Some("A positive number!")
     |   else None // A number less than 0?  Impossible!
     | }

getAStringMaybe: (Int)Option[String]

scala> def printResult(num: Int) = {
     |   getAStringMaybe(num) match {
     |     case Some(str) => println(str)
     |     case None => println("No string!")
     |   }
     | }
printResult: (Int)Unit

scala> printResult(100)
A positive number!

scala> printResult(-50)
No string!

getAStringMaybe方法返回Option [String]。Option是一个具有两个子类的抽象类,类Some和对象None。这是实例化Option的唯一两种方法。所以getAStringMaybe可以返回一个Some [String]或None。Some和None是大小写类,所以你可以使用方便的match / case结构来处理结果。没有一个对象表示没有方法的结果。

Option [T]返回类型的目的是告诉调用者该方法可能以Some [T]的形式返回T,或者返回None来表示没有结果。通过这种方式,调用者可以知道他什么时候做,不需要检查一个好的返回值。

另一方面,只是因为一个方法被声明为返回一些非Option类型并不意味着它不能返回null。而且,声明为返回Option的方法实际上可以返回null。所以这项技术并不完美。

这是一个巧妙的技巧,但是你能想象一个代码库:在选项[This]和Option [That]遍布整个地方,以及随后的所有匹配块?我想说谨慎使用Option。

Unit

这是另一个容易使用的。 Unit是不返回任何值的方法的类型。 听起来有点熟? 这就像Java中的一个void返回类型。 这是一个例子:

scala> def doThreeTimes(fn: (Int) => Unit) = {
     |   fn(1); fn(2); fn(3);
     | }
doThreeTimes: ((Int) => Unit)Unit

scala> doThreeTimes(println)
1
2
3

scala> def specialPrint(num: Int) = {
     |    println(">>>" + num + "<<<")
     | }
specialPrint: (Int)Unit

scala> doThreeTimes(specialPrint)
>>>1<<<
>>>2<<<
>>>3<<<

在doThreeTimes的定义中,我们指定该方法使用一个名为fn的参数,其类型为(Int)=> Unit。这意味着fn是一个方法,它接受一个I​​nt类型的单个参数和一个Unit的返回类型,这就是说fn不应该像Java void函数一样返回一个值。

是的。这些是Scala中的“虚无”项目。如果你知道更多,请发表评论!当你拿起Scala的时候,有很多东西需要学习,但作为回报,你会得到一种令人难以置信的表达和简洁的语言。

参考:

http://www.nickknowlson.com/blog/2013/03/31/representing-empty-in-scala/

https://sanaulla.info/2009/07/12/nothingness-2/




 
  • 4
    点赞
  • 0
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

<p style="color:#666666;"> <span style="color:#FF0000;"><strong>适合人群:</strong></span> </p> <p style="color:#666666;"> 1、具有一定Python语言基础,有一定的web前端基础,想要深入学习Python Web框架的朋友; </p> <p style="color:#666666;"> 2、学习完“跟着王进老师学开发Python篇”“跟着王进老师学Web前端开发”的朋友; </p> <p style="color:#666666;"> 3、有Django基础,但是想学习企业级项目实战的朋友; </p> <p style="color:#666666;"> 4、喜欢 Django 框架并想深入研究的朋友; </p> <p style="color:#666666;"> 5、有一定的数据库基础 </p> <p style="color:#666666;"> <br /> </p> <p style="color:#666666;"> <span style="color:#FF0000;"><strong>课程目标:</strong></span> </p> <p style="color:#666666;"> 本系列课程是从零基础开始并深入讲解Django,最终学会使用Django框架开发企业级的项目。课程知识点全网最详细,项目实战贴近企业需求。本系列课程除了非常详细的讲解Django框架本身的知识点以外,还讲解了web开发中所需要用到的技术,学完本系列课程后,您将独立做出一个具有后台管理系统,并且前端非常优美实用的网站。对于从事一份Python Web开发相关的工作简直轻而易举。 </p> <p style="color:#666666;"> <br /> </p> <p style="color:#666666;"> <span style="color:#FF0000;"><strong>课程内容:</strong></span> </p> <p style="color:#666666;"> <strong>一、融汇贯通</strong> </p> <p style="color:#666666;"> 将Python语言Django基础知识,以实际应用为媒介,有机组织、融汇贯通。让你的理论与实践结合起来,由知道变成会用。使用了大量的Django高级特性Bootstrap前端框架,展示了真实的项目部署过程。 </p> <p style="color:#666666;"> <br /> </p> <p style="color:#666666;"> <strong>二、贴近实战</strong> </p> <p style="color:#666666;"> 本系列课程为项目实战:超市前端收银系统的开发,项目包含了如下几个模块:系统登录页面、收银模块、管理人员的主界面、收银明细查询。从零开始展示了开发过程。包含了开发前的需求分析、数据库的设计、前端页面的准备、登录模块的实现、收银模块的实现、主界面的动态加载、收银明细的查询。课程具有极强的实战性。 </p> <p style="color:#666666;"> <br /> </p> <p style="color:#666666;"> <img src="https://img-bss.csdn.net/201902221412375430.png" alt="" /> </p>
©️2021 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值