Scala讲座:类定义和构造函数

  序言

  到这为止牛尾先生作了一下Scala语言的介绍,接下来以微型旅游的形式做一下有关Scala语法特点的探险。如果是初次接触的读者可以大略的读一下第一和第二回的讲座,就可以顺畅地读懂本文了。

  这次旅行准备访问的是,类定义和构造函数;混合Scala与Java程序以及与Java语言在语法上的差别;称为特征(Trait)的mixin型多重继承;函数定义和函数式编程;类型层次和集合;模式匹配;XML文本操作;等主题。

  首先,作为复习我们先整理一下Scala语言的要点。

  ● 事实1:Scala中可以简单使用所有Java类,Java中也可以自由调用Scala类。Scala类还可以定义为Java类的子类。也就是说,庞大的已有Java、J2EE、Java ME和CLDC资源可以被更有效和合理地应用了。(在Net上,虽然现在的版本还不支持,1.x版曾经支持过,将来也有复活的计划)

  ● 事实2:Scala在JVM上被执行,编译后的代码执行性能基本与Java代码不相上下。结果是比大多数脚本语言的速度都快一位数以上。

  ● 事实3:Scala一方面是纯面向对象的语言,另一方面在这框架中提供了完全的函数式编程的功能。Scala的所有数据都是对象,函数也是对象,可以作为数据来操作。

  ● 事实4:Scala在对于开发Javac和Java Generics有贡献的Martin Ordersky教授所率领的强大的开放体制下被开发,不是实验室的实验品,而是将来可以期待的通用编程语言。Scala发布的频率非常快,文档也很丰富,现在的版本是Scala2.7.1 final(2008/8)。

  类定义和构造函数

  那么,定义一下类吧。首先定义一下在语言介绍中一直用到的Person类。首先是Java类

  publicclassPerson { privateStringlastName;//姓privateStringfirstName;//名privatePersonspouse;//配偶的Person对象publicPerson(Stringfn,Stringln,Persons) { lastName=ln;firstName=fn;spouse=s; } publicPerson(Stringfn,Stringln) { this(fn,ln,null);//未婚时没有配偶} publicStringgetFirstName() { returnfirstName; } publicStringgetLastName() { returnlastName; } publicPersongetSpouse() { returnspouse; } publicvoidsetSpouse(Personp) { spouse=p; //没有考虑婚姻对姓和名的影响} publicStringintroduction() { return”我的名字是,”+firstName+””+lastName+ (spouse!=null? “对方的名字是,”+spouse.firstName+””+spouse.lastName+”。”: “。”); } }

  下面是用Scala写的同样内容

  classPerson(fn:String,ln:String,s:Person) { vallastName=ln;//没有private修饰符则认为是publicvalfirstName=fn;//从构造函数的参数类型推断为Stringvarspouse=s;//从构造函数的参数类型推断为Persondefthis(fn:String,ln:String)={this(fn,ln,null);} defintroduction():String= return”我的名字是,”+lastName+””+firstName+ (if(spouse!=null)”对方的名字是,”+spouse.lastName+””+spouse.firstName+”。”else”。”); }

  从行数来看大概缩短为1/3,代码变得非常简洁了。用val来定义常量,var来定义可再赋值的实例属性。用def来定义方法。Scala的目的之一就是使书写的代码更简洁易读。

  在Scala中实例属性默认为public,可以用该实例属性名来直接存取属性的值。

  scala>valp0=newPerson(“Fei”,”Zhang”) p0:Person=Person@6e9b6a scala>p0.introduction res1:String=我的名字是,ZhangFei。

  而且Scala对于调用方法的“.”符号,在不发生歧义的情况下可以替换为空格。但是,这里不能加上空的参数表()。

  scala>p0firstName//同p0.firstName等同 res3:String=Fei scala>p0spouse//现在未婚,所以spouse的值为null res4:Person=null scala>p0.spouse()//注意,Scala中.m和.m()的含义不同 :6:error:p0.spouseoftypePersondoesnottakeparameters p0.spouse()

  接下来那让ZhangFei结婚吧。先准备好女方DiaoChan对象,然后把她设置到p0的spouse属性。这时构造函数第三个参数为配偶,所以赋予p0。

  为了防止误解先说明一下,p0最初是用val来定义的所以是不可再赋值的,不过改变p0所指对象的内部状态还是可以的。因此,如下所示结婚后还可以让他再婚。

  scala>p0spouse=newPerson(“Chan”,”Diao”,p0)//DiaoChan和ZhangFei结婚 scala>(p0spouse)firstName//写成p0spousefirstName就会出错 res6:String=Chan scala>p0spouse=null//ZhangFei离婚 scala>p0spouse=newPerson(“Shi”,”Xi”,p0)//和XiShi再婚

  定义Scala的类比较有趣的是定义基本(primary)构造函数时在类名称后直接加上构造函数的参数表。基本构造函数参数的类型不可省略(包括模式匹配,这是对象的类型信息的基础,不能省略也是当然的)。另一方面,可以注意到类型定义中的变量定义没有指定类型,这都是靠从构造函数参数的类型推断出来的。

  而且声明为def this(ln:String, fn:String)的派生构造函数也是从基本构造函数而来的。函数体内通过调用this(ln, fn, null),给基本构造函数的第三个参数赋予null来实现为了未婚人士准备的只有两个参数的构造函数。

  这个类定义还可以缩短如下

  classPerson(valfirstName:String,vallastName:String,varspouse:Person){ defthis(fn:String,ln:String)=this(fn,ln,null) defintroduction=”我的名字是,”+lastName+””+firstName+ (if(spouse!=null)”,对方的名字是,”+spouse.lastName+””+spouse.firstName+”。”else”。”) }

  由于在类中基本构造函数的参数定义前加上val或var后,对应的实例属性就会被定义,所以原来的属性定义就不需要了。而且,编译器会自动追加用于存取这些属性的方法。Scala中基本上可以去除语句尾部的“;”符号,这里也都去除了。

  scala>valp1=newPerson(“Yu”,”Guan”,newPerson(“ZheTian”,”Wu”)) p1:Person=Person@904f75 scala>p1.lastName res7:String=Guan scala>p1.spouse res8:Person=Person@2e879

  上述程序中描述对象的字符串比较难解,下面就扩展一下类使他显示姓和名吧。任何对象的文字描述是由对象的最根类Any的toString:String方法来实现的。在各个类中使用自己的实现来覆盖这个方法就可以了,这里的显示格式为[姓:firstName 名:lastName 配偶:没有或(姓:firstName 名:lastName)]。另外,Scala中覆盖父类的方法一定要加上override修饰符。

  classPerson…{… overridedeftoString:String=super.toString+”[姓:”+lastName+”名:”+firstName+”配偶:”+(if(spouse!=null)”(“+spouse.lastName+”,”+spouse.firstName+”)”else”没有”)+”]” …}

  下面是修改后的效果

  scala>valp1=newPerson(“Yu”,”Guan”,newPerson(“ZheTian”,”Wu”)) p1:Person=Person@4a0ac5[姓:Guan名:Yu配偶:(Wu,ZheTian)] scala>p1 res0:Person=Person@4a0ac5[姓:Guan名:Yu配偶:(Wu,ZheTian)]

  Scala讲座中类定义和构造函数的内容就到这里。

在旅途中,我遇见了你,你我相识是缘分!

Scala讲座:类定义和构造函数

相关文章:

你感兴趣的文章:

标签云: