包和函数定义以及类型声明
不过还是想把结婚这个动作明确表现出来呀,那就试着写一下吧。对于函数式+面向对象的Scala来说有两种考虑方式。
第一个是面向对象的方法,当然就是让Person类持有表示结婚的方法getMarriedTo(对方:Person)了。另一个就是函数式方法,结婚是那女双方的事情,只在一方的Person类中定义getMarriedTo方法可能也不太确切,可以在Scala特有的单例对象中(object)定义marry方法来描述结婚这一事件。下面的例子中将Person类移到了Life包中,并在Life包中定义了同名的单例对象(singleton object),然后在Person类和对象中定义了getMarriedTo和marray方法。另外,因为这里的Person单例对象与Person类同名
且在同一个源文件里,所以他们互相又成为伴生对象和伴生类。
package life { class Person(val firstName:String, val lastName:String, var spouse:Person) { def this(fn:String, ln:String) = this(fn, ln, null) def introduction = "我的名字是," + firstName + " " + lastName + (if (spouse != null) ",对方的名字是," + spouse.firstName + " " + spouse.lastName + "。" else "。") def getMarriedTo(p : Person) { this.spouse = p; p.spouse = this } override def toString : String = super.toString + " [姓: " + lastName + " 名: " + firstName + " 配偶: " + (if (spouse != null) " ("+ spouse.lastName + "," + spouse.firstName + ")" else "没有") + "]" } object Person { def marry(p1: Person, p2: Person): Unit = { p1.spouse = p2; p2.spouse = p1 } } } |
上述Unit类型代表不返回任何值,相当于Java中的void。如果想把Person类以别的名称来使用则可以用import语句来声明别名。比如以下程序中为Person类定义了名为Man的别名。
scala> import life.{Person => Man} import life.{Person=>Man}
|
实际上述语句与以下声明type别名的语句是一样的
- scala> import life.Person
- import life.Person
- scala> type Man = Person
- defined type alias Man
|
正像这样,我们可以利用Scala的交互式环境一边写简洁的代码一边一点一点地确认结果来进行开发。还有,包和类都可以嵌套定义,这里就省略了。
Scala中操作符也是方法
实际上Scala并没有内嵌在语言中的操作符。加法+、乘法*、减法-、除法/、字符串连接+和列表连接++等操作符都是Int、String或List等类型中的方法(有时可能是父类中的方法)。因此,操作符中的特殊字符在Scala中可以被用作方法名称的一部分,这对于定义迷你语言(DSL,特定领域语言)来说是非常重要的。
那么,将“m先生和f女士结婚后f女士的姓变为m”这一动作以“m < + f”来表示吧。在Scala中这
表示“对接受对象m适用方法< +,参数为f”,是“m.< +(f)”的简化形式。马上就在Person类中定义一个两元操作符方法“< +”吧。虽然返回值也可以是Unit,这里就以接受对象自己为返回值吧。
class Person … { … def < +(p : Person): Person = { this.getMarriedTo(p) p.lastName = this.lastName this } … } |