By 高焕堂
洞庭国际智能硬件检测基地
Q-01: 如何使用Scala的Singleton机制来表达Class-level的数据。
Answer:
在面向对象编程(OOP,Object-Oriented Programming)概念里,属性(Attribute)和函数(Function)都分为两个不同级别(Level)。例如,厦门的科技谷(厦门)公司的大数据平台上,定义了数百个航空公司的类(Class),包括:东方航空公司(ChinaEasternAirlines)、南方航空公司(ChinaEasternAirlines)、长荣航空公司(EvergreenAirlines)等等。其中,每一架飞机都是一个实例(Instance)或称对象(Object)。于是可看出来,无论属性或函数都分为两个级别:
- Instance-level(实例级别或称对象级别):这是一般大家都知道的,例如每一架飞机都是一个实例或对象,各自都有它的厂牌、载客量、年龄等属性数据。
- Class-level(类级别):例如,长荣航空公司的飞机数量,是重要的属性数据,但不是某一架飞机(Instance)的属性数据,而是属于整个EvergreenAirlines类的属性数据。当我们再问:长荣航空公司的飞机数量时,常常相当于在问:EVA(EvergreenAirlines)类目前共创建了多少个对象(实例)呢?像这种数据,就称为Class-level的属性数据。
既然有了Class-level的属性,为了存取(Access)这种属性的数据值(Value),当然我们就会定义某些函数来存取或处理之。这种函数,就称为Class-level的函数或方法了。
// Instance-level 属性和函数的定义
class EVA {
var manufacturer : String = ""
var capacity : Int = 0
var mfr_date : String = ""
def pr_capacity() {
println(capacity)
}
}
// Class-level 属性和函数的定义
object EVA {
var instance_amount : Int = 0
def apply() {
instance_amount = instance_amount + 1
return new EVA
}
def pr_amt() {
println(instance_amount)
}
}
// myApp
object myApp {
def main( args: Array[String] ) {
val a1 = EVA()
val a2 = EVA()
val a3 = EVA()
EVA.pr_amt
}
其中的capacity是Instance-level属性,pr_capacity是Instance-level函数。而instance_amt是Class-level属性,而pr_amt是Class-level函数。在执行这个程序时,首先载入(Load)代码到内存(Memory),让VM来执行之。
当执行到指令: val a1 = EVA(),此时先执行等号(=)右边的EVA(),拿object EVA定义来创建一个对象,来表达EVA类本身,也就是说,EVA类本身就是一个对象,所以就创建一个VEA类的对象,来储存EVA类有关的属性(数据)值。例如,定义一个instance_amt属性来纪录目前EVA类共创建了多少个对象(长荣航空有多少架飞机)。
接着执行到apply()函数,拿class EVA定义来创建一个对象,来表达一架长荣飞机,记录该架飞机的属性值。并且,将EVAobj的instance_amt值加1,表是长荣航空增加了一架飞机。
继续执行到:
val a2 = EVA()
val a3 = EVA()
就创建更多的<长荣飞机>对象,并更新了<长荣飞机类>对象里的instance_amt值。
此时,在内存里共有4个对象,包括1个<EVA类>(本身的)对象,以及3个<EVA实例>对象(如上图里的a1, a2和a3)。以上,藉由长荣航空的例子,说明Scala语言如何表达Instance-level属性和函数,以及表达Class-level属性和函数。
~ end ~