有java背景的人,很清楚java是如何定义构造方法以及继承的。在scala里面,继承和java有些相似。但是构造方法的定义,就不大一样了,应该说是差别还是很大的。在java里面,定义构造方法,就是定义一个没有返回值类型的与类同名的方法。
如下:
1 package com.shihuc; 2 3 public class Person 4 { 5 private String lastName; //姓 6 private String firstName; //名 7 private Person spouse; //配偶的Person对象 8 public Person(String fn, String ln, Person s) 9 { 10 lastName = ln; firstName = fn; spouse = s; 11 } 12 public Person(String fn, String ln) 13 { 14 this(fn, ln, null); //未婚时没有配偶 15 } 16 public String getFirstName() 17 { 18 return firstName; 19 } 20 public String getLastName() 21 { 22 return lastName; 23 } 24 public Person getSpouse() 25 { 26 return spouse; 27 } 28 public void setSpouse(Person p) 29 { 30 spouse = p; 31 } 32 public String introduction() 33 { 34 return "我的名字是," + firstName + " " + lastName + 35 (spouse != null ? 36 " 对方的名字是," + spouse.firstName + " " + spouse.lastName + " 。" : 37 " 。"); 38 } 39 }
但是,scala里面,可以看到:
1 package lession2 2 3 class Person(fn: String, ln: String, s: Person){ 4 val firstname = fn 5 val lastname = ln 6 var suporse = s 7 8 println("primary constructor") 9 10 def this(fn : String, ln : String) { 11 this(fn, ln, null) 12 } 13 14 println("I am testing code") 15 16 def introduction() : String = { 17 return "我的名字是, " + lastname + " " + firstname + 18 (if (suporse != null) { 19 " 对方的名字是, " + suporse.lastname + " " + suporse.firstname + "。" 20 }else { 21 "。"; 22 }) 23 } 24 } 25 26 object PersonTest{ 27 def main(args: Array[String]){ 28 var p = new Person("shihu", "CHENG") 29 println(p.introduction()) 30 } 31 }
虽然scala的写法变得比java简洁了很多,这个是值得表扬的,但是构造函数的定义就有很大的不同。
1. 先说主构造函数,也就是英文资料中说的primary constructor,它是和类的定义混杂在一起的,即定义类的时候,就指明了这个类的成员变量参数,还有,就是在类中,除了def定义的成员函数之外的所有操作,都可以看作是构造函数的行为组成部分,不管是变量赋值还是函数调用。而java的类定义和构造函数的定义是分开的。
2. 再说派生的构造函数,即java中可以定义多个构造函数,这点,在java里非常简单,就是方法的重载呗。但是,在scala里面,要定义多个构造方法,就必须直接或则间接的调用主构造函数。而且调用的时候,必须通过关键字this来操作。正如上面scala代码中的辅助构造函数:
1 def this(fn : String, ln : String) { 2 this(fn, ln, null) 3 }
需要注意的是,辅助构造函数名必须是this,而且必须调用主构造函数实现参数的传递(直接或则间接,本例子是直接调用,因为只有一个辅助构造函数)。
3. 在scala中,若有继承,那么,只有主构造函数才能将参数的值传递到父类的构造函数中去。
4. 在scala中,若子类继承了父类,但是想在子类中重写父类的某个函数,则在子类中必须用关键字override对父类的函数进行改写, 否则会出现语法错误。要想调用父类的同名函数,可以通过super关键字进行,这点与java是一致的。