定义类
// 定义类,包含field以及method class HelloWorld { private var name = "Leo" def sayHello() { println("Hello" + name)} def getName = name } defined class HelloWorld // 创建类对象,并调用其方法 scala> val helloworld = new HelloWorld helloworld: HelloWorld = HelloWorld@4f49f6af scala> helloworld.sayHello() // 也可以不加括号 HelloLeo scala> print(helloworld.getName) // 不能加括号,因为定义方法的时候没有加括号 Leo
封装(setter与getter)
- 定义不加参数的var filed,Scala会将该字段定义为private,并提供public的getter和setter方法
- 如果使用private修饰field, 则生成的getter和setter也是private的
- 如果定义val field, 则只会生成getter方法
- 如果使用private[this]修饰field,则不会生成getter和setter方法
总结:Scala提供的四种修饰符:var、val、private、private[this]
class Student { var name = "sparks" } defined class Student scala> val spark = new Student spark: Student = Student@6337c201 // 调用自动生成的setter和getter方法 scala> print(spark.name) sparks scala> spark.name = "hahah" spark.name: String = hahah
如果希望能够自己对getter和setter进行控制,则可以自定义getter与setter方法,使用field和fild_=的方式。
class Student{ private var myName = "Sparks" def name = "Your name is" + myName def name_=(newName: String) { myName = newName } } val spark = new Student print(spark.name) spark.name = "Leo"
注意:自义定setter方法一定要注意scala的语法限制,签名、_=参数间不能有空格。
private[this]的详解
如果字段是private修饰的,那么代码这个字段时私有的,在类的方法中,可以直接访问类的其他对象的private field。
例如:
class Student { private var myAge = 0 def age_=(newValue: Int){ if(newValue>0) { myAge = newValue} else print("illegal age!") } def age = myAge def older(s: Student) = { myAge > s.myAge // 调用另一个对象s的私有字段并不报错 } }
但是如果是用private[this]修饰,那么意味着该对象私有字段只有本对象内才可以访问,上面的代码就会报错
<console>:16: error: value myAge is not a member of Student myAge > s.myAge // 调用另一个对象s的私有字段并不报错
Java风格的getter和setter方法
如果要让scala自动生成java风格的getter和setter方法,只要给field添加@BeanProperty注解即可。
此时会生成4个方法,name: String、 name_=(newValue: String): Unit、 getName(): String、 setName(newValue: String): Unit
// 定义类 import scala.reflect.BeanProperty class Student{ @BeanProperty var name: String = _ } defined class Student // 测试类 scala> val s = new Student s: Student = Student@5f303ecd scala> s.setName("leo") scala> s.getName() res9: String = leo scala> s.name res10: String = leo scala> s.name = "spark" s.name: String = spark scala> s.getName() res11: String = spark // 定义Java风格类的第二种方式 class Student(@BeanProperty var name: String)
构造函数
主构造函数
在Scala中,主constructor是与类名放在一起的,而且类中没有定义在任何方法或者是代码块之中的代码,就是主constructor的代码,这点很新颖,但感觉没有java清晰。
class Student(val name: String, val age: Int) { println("your name is " + name + ", your age is " + age) } defined class Student scala> val s = new Student("spark", 30) your name is spark, your age is 30 s: Student = Student@43b40233 // 还可以使用默认参数 class Student(val name: String = "leo", val age: Int = 30) { println("your name is " + name + ", your age is " + age) } defined class Student // 这样新建对象时就不用传递参数了 scala> val s = new Student your name is leo, your age is 30
注意:如果主constucutor传入的参数什么修饰都没有,比如name: String, 那么如果类内部的方法使用到了,则会生命为private[this] name; 否则没有该field,就只能被constructor代码使用而已。
辅助构造函数(this)
Scala中,可以给类定义多个辅助constructor,类似于java中的构造函数重载
辅助constructor之间可以互相调用,而且必须第一行调用主constructor
// 定义类 class Student{ private var name = "" private var age = 0 def this(name: String){ this() // 必须调用主构造函数 this.name = name } def this(name: String, age:Int) { this(name) // 必须调用主构造函数 this.age = age } } defined class Student // 测试类 scala> val s1 = new Student s1: Student = Student@387bf2d9 scala> val s2 = new Student("sparks") s2: Student = Student@5e746d37 scala> val s3 = new Student("spark", 23) s3: Student = Student@5524b72f
类部类
在Scala中,同样可以在类中定义内部类;但是与java不同的是,每个外部类对象的内部类,都是不同的类
// 定义内部类 import scala.collection.mutable.ArrayBuffer class Class{ class Student(val name: String){} val students = new ArrayBuffer[Student] def getNewStudent(name: String) = { new Student(name) } } defined class Class scala> val c1 = new Class scala> val s1 = c1.getNewStudent("spark") scala> c1.students += s1 scala> val c2 = new Class scala> val s2 = c2.getNewStudent("leo") scala> c1.students += s2 // 出错,因为每个外部类对象的内部类都是不同的类 <console>:15: error: type mismatch; found : c2.Student required: c1.Student c1.students += s2 ^