00:00
接下来我们来介绍一下skyla里边比较特殊的一大类数据类型,这就是我们所谓的空类型,前面我们讲到skyla类型系统的时候也发现了啊,在skyla里边所谓的空其实是有不同的含义的,这就是我们所说的啊,Skyla分成两大类型。值类型和引用类型,Any value和any reference,那现在我们所谓的空呢,当然也就分为了空值和空引用啊,那当然另外还有一个比较特殊的,就是什么都没有的那个空叫做nothing,那接下来我们就给大家把它们完全列出来,分别说一说它们各自的特点。首先unit unit非常简单,就是我们所所说的空值嘛,它其实就相当于其他语言里边,特别是大家熟悉的Java里边的VO,我们一般用它是表示某一个方法,某一个函数的返回值为空,这个时候我们就把它的类型写作unit。
01:03
所以它其实就是any value啊,值类型的一个子类,它表示的是空值,那么它对应的啊,这本身unit是一个数据类型,是一个类,它里边呢,只有一个对象实例,就是所谓的空括号,写出来的话,一般我们都用空括号来做一个表示,这个是unit空值,那与之对应的呢,还有空引用,空引用大家就更加熟悉了,和其他语言里边啊,跟Java里边也类似,空引用就是小写的null,那那么它其实是大写的nul,那这个类这个类型的唯一的实例啊,所以这里边我们就用完整的类型系统把它都包含在里边了,空值就是unit,空引用就是脑。那对应的实例呢?空值是空括号,空引用是小写的nu,那除了unit和nu之外,另外还有一个比较特殊的类型叫做nothing,哎,我们知道在scla里边,Nothing它其实是一个最底层的一个类型,也就是说它是其他所有一切scalela类型的子类啊,那所谓的nothing,我们知道英文里边就是没有任何东西嘛,什么都没有。所以在这种场景下,我们其实就是我既不管当前它到底是空值还是空引用,也就是我根本不管它到底是直类型还是引用类型,我只考虑现在就是什么都是空,啥都没有,这种情况我们指定的类型就是nothing,那它到底有什么应用呢?到底有什么含义呢?我们一般是把它应用在某一个函数,某一个方法,当它就完全不会正常返回的时候,比如说中间就直接抛出异常的时候,那这个时候大家想。
02:50
它既然中间抛出异常了,根本不返回,那它的返回值能定义成空值unit吗?那显然不能,那能定义成空影用nu吗?也不能,因为他根本就不会返回我们所谓的返回值的类型,你至少它得返回了之后,我们才能判断它类型嘛,那现在根本不返回,返回值类型是什么呢?就是nothing啊,所以假如说啊,我们根本就没有正常返回值这样一个方法啊,中间抛出了异常,我们这里边就直接可以用nothing来指定当前的返回值类型。
03:23
那为什么nothing又可以作为所有其他类型的子类要有这样一个特别的定义呢?那主要就是方便我们在写代码的时候进行兼容,因为大家想,我们在一段代码里边,有可能我们某些条件下是正常返回一个值的,那有可能是返回一个int类型的值,有可能返回一个string,也有可能返回一个scla的类啊,一个集合类型,一个引用类型,这都是有可能的。但是呢,在另外一些特殊的场景下,我们可能就会直接抛出一个异常。那怎么样兼容这两种不同的情况呢?诶大家其实就发现了,抛出异常的时候,它的返回其实应该指定为nothing,诶大家知道在Java里边,如果你要是兼容这种抛出异常的情况的话,那是在方法外边就得定义出来它throws什么样的一个异常,而我们现在在scla里边呢,不需要那样的关键字了啊,就是只要用nothing这个类型把它兼容起来就可以了,因为它是所有类型的子类嘛,那我们在外层定义的时候,你就该是返回int,就返回类型,呃返回int该是string,就返回string string,那抛出异常的时候,即使是它返回了nothing,它也可以作为一个int类型啊,也可以作为string类型啊,这样就完全兼容了。
04:39
啊,如果这样说起来大家还是感觉有点难以理解的话,我们就还是在代码里边做一个实际的测试和实现,我们来看一看tla里边的空类型到底是怎么样去用的,首先我们还是先看一下空值。
05:02
也就是我们所说的类型,那么对于分类型而言,我们在测试的时候其实也非常的简单,只要自己直接去定义一个。最简单的这个方法,然后让它返回值的类型是一个unit,其实就可以了啊,那所以接下来我们其实可以直接先去定义一个方法。大家还记得定义方法的时候,关键字是EF,然后比方说我们就定义随便叫叫做M1,也不需要有任何的参数,它的返回值呢是unit,后边是法函数体,那里边我们最简单的直接打印输出一句话。当前就应该没有任何的返回值嘛,只是控制台输出嘛,所以当前我们就随便说一句,M1A调用执行,大家其实知道这个时候如果我直接在这里调用M1的话,不然就会输出这样的一行,呃,内容啊,直接在控制台输出,那这里如果我还想把它得到的结果,这个调方法调用的结果再付给另外一个变量,看看这个值是什么的话,当然可以这样去做一个书写,下边我们可以把这个A做一个打印输出,我们看一看逗比得到的东西是什么。
06:27
我们看到最终这里边首先会有一句M1被调用执行啊,因为大家看在给A赋值之前,我们首先要把M1做一次调用,才能把得到的结果付给A嘛,所以这一次调用就会输出这样一句话,而最终A的值呢,是这里print来打印出来的一个空括号,这就是我们说的啊A这里我们没有写类型,如果要自动是JA塔编译器给我们做自动推断,如果完整的写出来的话,补全的话,应该它的类型就是unit,那么这里把它的类型unit写出来之后,我们就会发现。
07:06
于unit类型而言,它里边的唯一的一个实例值其实就是空括号啊,我们可以看到这个非常的明确啊,A的值输出就是空括号,这就是所谓的空值和一种特殊的数据类型。然后我们再来看一下第二种是所谓的通饮用nul,那大写的这是表示类型,那如果是小写的话,当然就表示里边是一个呃,具体的这个实例了啊,就是我们所说的空的那个实例。那这里首先我们想一下,假如我们定义一个,比方说我定义一个N,它是int类型,能直接给一个nul这样的一个一个一个空吗?我们可以直接运行一下,看看这个是否是正确的,哎,大家看这个不对,对吧。
08:00
这里尽管idea里边没有报错,没有提示,但是如果大家直接运行的话,你会发现当前的这个int类型是没有办法去接收一个那一个空引用作为它的值的,所以这种写法是错误的,就是一个值类型不能接收。那引用作为它的内容,那什么样的它的变量才可以接收呢?啊,这个大家也比较清楚啊,比方说这里啊,如果我们要改变值的话,我们可以用R啊定义一个变量来,我定义一个student,前面我们不是设置过这个student类吗?可以直接去new一个student里边类20,我先定义这样的一个student,它是它的类型,如果这里要写的话,这个很明显应该是一个student类型。那么接下来如果说我还要对它做一个别的赋值,让它等于none的话,A大家看这其实是完全没有问题的。最终如果我要把这个student做一个打印突出的话,大家就会看到输出的结果是一个闹。
09:12
这里边空引用唯一的一个对象实例就是小写的a now啊,这里边student可以复制为那的前提就是它是一个引用类型,我们说skyla Java,所有的类对应的对象都是引用类型啊,所以这里边我们可以给它赋值,赋为一个nu,这就是关于空引用的用法,然后最后还有一个非常特殊的所谓的就是什么都没有的那个空啊,这确实是相对来讲比较特殊,我们也说了,它一般呢,作为没有正常返回值的方法的返回类型,而且呢,这里边就是非常直观的告诉我们这个方法,哎,它就不会有返回了,它中间可能就直接抛异常退出了,所以我们看一个具体的例子,还是第一个方法,我们把它叫做M2,比方说这里我们还有一个具体的。
10:05
分数啊,传一个N进来,Int类型的N进来,然后呢,它的类型假如说它就不会正常的返回,我这里边就要把它的返回类型定义成nothing,那里边我们看一下到底是怎么样去定义的啊,大家看这里首先是报错的,因为如果这里边我们不抛异常的话,它的返回值默认其实应该是unit,就是空嘛,什么都不返回嘛,空值嘛,所以这个时候如果我们定义成了nothing的话,那在里边其实就必须要返回一个。啊,就抛出一个异常,把它作为一个返回,你比方说我们这里边直接throw,你有一个on pointer exception样的话,目前的这一个定义就是完全正确的,当然对于这样一个类型而言,大家可能会想到我直接定一个B量啊,接收当前比方说M二传一个零进来,我要接收它投影之后的返回值给到B,然后打印B的值,它又应该是什么呢?有没有具体的这个对象输出呢?啊,大家自然想到了,这是肯定没有的,因为nothing这个类型表示它就根本不会正常返回,那所以这个B当然就接受不到具体的值了,我们这里边中间在调用这个M2的时候,中间直接就抛出异常,直接就退出了,哎,所以这里边也不会执行这个打印B的这个结果,我们可以看一下当前的执行的效果是什么样的,那当然就是在这儿直接抛了一个空指针异常。
11:36
这是关于这个nothing的直接的用法,那大家可能会想到,如果要是这么用的话,这好像。这这就确定它一定是要抛出异常了,对吧,这个好像没什么意义啊啊,那更多的使用,大家会想到它可能是要去用在一些不同的场景里边,比如说我们在这里边不不是有一个输入的。
12:00
N数叫做N吗?那我们可以根据N做一个条件判断,假如当前的N等于零的话,那么这个时候我们不要直接这里面就直接return return一个return一个当前的这个零直接返回就可以了,那如果说哎。不为零的时候,这个时候我再直接抛出一个控制人异常啊,或或者大家可能会想到那个等于零的时候,这个好像抛异常更加的直观一点,对吧?诶,那我在这种情况下直接抛一场,那如果要是要归零的时候,直接return从前的。那大家会发现现在的话这个就有问题了,因为如果要return n的话,是一个整形啊,Int类型啊,这个时候整形。我们在else分支里面返回一个整形,而在if分支里边呢,抛出异常,返回一个nothing,那它综合起来,我们这个代码块返回的类型应该是什么呢?
13:00
那自然我们就想到了,应该是if和else里边返回类型的一个公共副类,那公共副类当然不能是nothing了。因为大家想到nothing是所有类型的子类啊,有同学可能想,哎,那你要是公共负类的话,我直接用那个any,那肯定没有问题对吧?上面这个直接定义成an肯定没有问题,是一般我们定义公共负类的时候,肯定是范围越小越好嘛。哎,所以在这里大家就想到了你这个int和这个nothing nothing是所有类型的词类啊,所以我根本就不用考虑这个nothing,我是不是直接看别的情形下,当前这个返回到底是什么类型,我这儿就返回什么类型就好。哎,所以大家看到如果说else里边我要返回的是一个int类型,我就直接认为当前方法返回的是int,如果要是想要抛出异常的话,诶,那我就直接这里边这是nothing嘛,Nothing也是一个int的子类啊。完全兼容在一起了,所以大家看,如果要是这样的一个场景的话,比我们。
14:00
可以做一个打印输出,把B的值和一个打印输出,我们就会看到M2调用的时候,如果它不等于零,那这里边就会正常的返回当前的N的值,所以B就等于二,就会把它再赋值给B了,那当然这里边我们省略了B的类型应该是in,就是关于scla里边所有的空值空类型啊,空值空引用以及nothing所有的空类型它们的用法。
我来说两句