00:00
接下来我们来了解一下scla当中比较特殊的一个概念,就是单例对象或者叫做伴生对象,这个概念呢,其实我们一开始在介绍hello word这个简单代码的时候也已经接触过了,那什么是单例对象呢?呃,我们看到在码里边每次要做测试的时候,我们直接创建文件的时候。定义的就是一个object,这就是我们所说的单立对象,它表示的是直接创建出来的就是一个对象,全局只此一份。下面呢?呃,这个main方法我们可以认为就类似于Java当中的public static void的may,就相当于是我们整个代码执行的主入口。那对于这一个概念,为什么skyla里边会有这样的一个设计呢?那就是我们所说的scla是一门完全面对对象的语言,所以在里边呢,它是没有静态操作。关于这一点我们要回忆一下Java,大家想到在Java里边是有static关键字的,那如果说我们用static关键字去修饰了一个属性或者方法的话。
01:11
呃,那自然我们就想到了,调用的时候,它还是基于对象去调用吗。诶,我们直接就是用类名,然后点属性,点方法直接去做调用了,这就不够面对对象,真正意义上的面对对象所做的任何操作一定都是对象的方法调用,所以大家看在scla里边干脆就把static关键字直接去掉了啊,要做到完全的面对对象,那我们自然想到这个直接大鼻一挥删掉比较简单,那如果说我们还是想实现类似于一个全局的静态的这样一个属性或者方法,那又应该怎么做呢?啊,因为有时候我们还需要跟Java去做一个交互,做一个兼容啊,诶,那。对应的策略解决方案就是单例对象,所以在scda当中是有这样的一种特殊的对象来模拟所谓的类里边的静态对象,这就是单例对象啊。那这里边还有另外一个名称叫做伴生对象,我们当时也给大家解释过,对于一个object定义关键字定义的对象而言,全局其实只有这么一份,所以我们可以把它叫做单立对象。而在底层呢,我们做过反编译之后,会发现它其实是最终会生成两个。
02:33
点class自解码文件,呃,如果我们把它看成Java类的话,那么其中的一个其实就跟当前的对象名称完全一样啊,我们可以把那个类叫做当前对象的半生类,而另外一个类呢,是有当前这个名称后面再加一个Dollar那样的一个类,我们把它叫做。当前伴生对象的所属类啊,所以这里面就有一个概念了,我们同样同一个名称,有一个类,还有一个对象,一个object,一个class,那么这两个。
03:08
对象和类,我们就把它们叫做相伴相生的,它们互为伴生,类是当前这个对象的伴生类,而对象就是类的伴生对象啊,所以是这样一个概念,我们平常做测试的时候呢,当然不会在定义它的半生类出来,但是在有一些场景里边呢,定义伴生类还是非常有必要的,那关于这个伴生类和伴生对象,他们声明出来又有什么用法,到底有什么好处呢?里边一个非常。重要的用法就是分利对象或者说伴生对象里边的属性和方法都可以直接由。当前的这个伴生类来进行调用啊,所以就是伴生类和伴生对象他们之间内部的属性和方法其实都是可以互相访问的,即使是private私有的属性和方法也是可以直接访问的啊,所以这一点就非常的方便啊,我们在使用的过程当中,有时候就可以直接把这个object。
04:11
单例对象啊,伴生对象里边直接放入我们之前想要的类里边的静态属性和方法,那声明的语法很简单,Object关键字后面加上伴生对象的名称。然后后边是画括号,里边就是我们定义的属性和方法,大家可以认为这里边就是静态的属性和方法,当成静态来用就可以了。那另外还有一个大家需要注意的是,伴生类和伴生对象,他们俩的名称必须完全一样,而且必须放在同一个文件里面,那接下来我们还是在代码里边做一个简单的测试,来看一看你怎么样去定义半生对象。新建一个Java的object,好,所以我们现在做测试的时候,创建的就还是一个立对象了啊,我们不会创建它的伴生类,是有这么一份的对象,只出现这么一份的对象,现在我们要测试的是object。
05:11
方法先写出来,现在我们要测试半生类和半生对象,所以首先我们先把类定义出来啊,那么这个类的话,我们就还是用student类,现在我们是STUDENT11啊,那这里我们其实可以直接用前面讲过的比较简单的。快捷的啊,直接定义属性的这种方法,比方说里边我们有两个属性,一个name,一个age,那么在这里可以直接前面加一个复制符,然后就说明当前既是。类的主构造器的参数,同时也是类里边的属性啊,所以这里name是一个string类型,另外还可以定义一个age是一个。里边我们其实就不需要其他的内容了,当然我们也可以定义一个方法啊。
06:03
呃,我们找一下之前啊,这里我们可以去做一个打印定义一个print iner这样一个方法。那这里边我们打印的是name age,以及另外还有一个school属性,那自然就想到了当前的这一个学生呢,有可能我们要定义的这个对象,具体的学生,他们里这个学校的这个属性可能都完全一样啊,所有的这个项目里边的学生都是属于同一个学校的,那这个时候我们就不需要把它直接定义在当前类的属性里了,这就相当于是一个静态的嘛。那怎么办呢?很简单,我们可以直接把它定义在产生对象里,那半生对象的定义,那就是object,关键字在这里,然后接下来那就是STUDENT11,名字必须跟上面的生类完全一样。那在下边可以以一个立一个属性,比方说我们叫STEM at,看如果要是这里定义了school的话,那其实直接可以在当前的半生类里边去做调用,那怎么样调用呢?诶调用的时候大家要注意啊,所有的属性和方法我们说都是基于。
07:28
对象去调用的嘛,都是对象的,呃,那这里边我们就要对象名称就是student实义,看讲这个student实义就有两种含义,一种是表示这里的类,另外一种就是直接表示这里的伴生对象,所以如果我们用这个半生对象的话,那然后直接点来看可以访问的录这个游戏,这样的话就可以把当前的所有信息都打印出来了。好,那有了这个之后,我们可以直接在上面来做一个具体的测试,那一个student,一个student。
08:05
11里边我们要传入对应的参数,呃,ALICE18,然后两个参数传进来就行了,School这个就相当于是静态在里面了,下来我们可以直接student报一下当前的printer方法,我们看一看效果到底怎么样。运行一下。我们可以看到当前可以把name age school3个属性都打印出来,这里边大家需要注意的是age,呃,Name和AGE2个属性是当前我们创建出来的STUDENT11对象实例里边的属性,而school呢,是当前它所属这个类的伴生对象里边的定义出来的属性,所以他们其实所属的位置是不一样的啊,我们可以把这个属性当做一个静态的属性来看,当然在这一个半生对象里边,我们也可以定义方法,那定义出来的方法就相当于我们在Java里边直接用static关键字定义出来的方法了啊,那有了这个功能呢,就会实现,就可以去很方便的实现一些其他的用法,比如说什么呢?呃,大家可能会想到,我们有时候可能希望有一些这个操作啊,不希望直接调这个class这个类,或者说当前这个对象里边相关的那些操。
09:32
操作,我希望把它做一个包装,只能在比方说通过。伴生对象object去做调用,嗯,那这里边一个最常见的用法是什么呢?就比如说我们在这儿如果要创建当前这个对象的话,是直接拗了一个对象实例出来,那有些场景下呢,我不希望在外边直接调用它的构造器,我希望让这个构造器私有化。不能随便调,哎,那你只要创建这个对象呢,必须通过我预先定义好的那些类似于工厂方法才能把它创建出来,那要实现这样的一个功能,怎么样去做呢?诶,这里边就可以有这样一个方法,我们可以在上边把构造方法私有化啊,那这个构造方法私有化大家可能会想那怎么办?前面加一个private关键字吗?那不对,那是把这个类定义成私有的了,那如果要是构造方法要私有化的话,在。
10:26
它的参数,大家看到参数列表这个小括号前边加一个private关键字,这样的话就表示主构造器私有化了,这个一加入之后,大家看到上面这里就报错了,因为已经不能直接调用当前的构造器去创造创建一个对象实例了,那我们怎么办呢?这就涉及到一个问题,我们可以通过本身对象去做一个定义来,比如说这里我们定义一个。
11:02
类的对象实例的。创建方法,或者我们叫呃,所谓的这个工厂方法,EF,第一个比方说这个就叫做new,一个student。对应的要用一个student的时候,我们也应该要传入一些参数,因为这里调用它构造器的时候得有name和age嘛,啊,所以这里面我们同样有一个name和一个age in。返回的就应该是一个STUDENT11类型的一个对象,然后接下来这里大家大家就看到了,这里我可以直接去new一个STUDENT11,把当前的name和位置放进来,为什么可以在这里调呢?因为前面我们说过,在当前的半生对象里边可以直接访问当前伴生类的私有成员和方法,诶,所以他们俩是完全不分彼此的相伴相生的,那这样的话,我们想要在外边调用的时候,那就必须去调用伴生对象里的已经包装好的这个new student这个方法了。
12:20
啊,所以接下来我们还是同样可以做一个测试,现在的写法不是去new一个STUDENT'11了,而是直接调用方法。那那调用方法的时候,我们应该调用谁的方法呢?当然是STUDENT11这个半生对象,而用student传入对应的name和H,下面我们可以直接调它的print方法,诶这样的话就实现了类似的功能,我们可以运行一下,大家可以看到得到结果还是完全一样。这里呢,我们需要另外给大家呃说一个特别的方法,在半生对象里边,我们可以定义一个比较特殊的方法叫做apply apply大家知道英文里边有应用的意思,那么这个apply在我们调用的时候呢,其实一样啊,这也是半生对象里边一个比较特殊,就是一个大家可以认为就是半生对象里边的一个普通的方法,我们把这个后面的定义呢,还是定义成跟前面创建一个实例是一样的。
13:28
那么大家就会看到跟u unit其实一样啊,我们只是换了一个名称而已,那在上面调用的时候呢,自然我们就想到了同样的这种方式,你比方说上面这个叫STUDENT1,上面这个我们叫STUDENT2 student2这里就不需要调new student方法,我可以直接调这个apply方法,后面我传另外的一个参数。都是完全没有问题的,要用的话得到结果当然也一样啊,我们知道这个方法名称本来就没什么影响啊,那这个apply它到底特殊特殊在哪里呢?诶,那是因为我们在skyla的编译器底层,对于。
14:10
半生对象或者单利对象的apply方法,它有一个特殊的优惠政策啊,就是我们在调用的时候呢,可以简洁就是直接把apply省略掉,也就是说我在调用apply方法的时候,可以直接就用当前的。产生对象或者利对象的名称后边直接加上调用apply的那些参数就可以了,括号里边传参就完事了,所以大家如果这么看的话,这就有点像什么呢啊,就好像是直接创建了一个STUDENT11的对象一样,而我们其实知道这里边其实调用的是。伴生对象的apply方法,而在这个apply方法里呢,我们创建了一个STUDENT11的具体的实例对象啊,这是当前我们这个使用伴生对象啊比较常见的一种用法,大家下来之后也可以把这个再测试一下,这种用法跟上面的student2.apply其实是完全等效的。
我来说两句