1课程大纲
scala既能面向对象、又能面向过程; 函数是一级成员
面向对象(封装、继承、多态)
1、定义一个简单地嘞
2、field的getter与setter详解
3、constructor详解,类的构造函数
4、内部类介绍
1 定义一个简单的类
1.1 定义类,包含field以及方法
函数没有参数,可以不用加加括号,不加括号()之后,在外部调用该函数的时候不用加括号。
在类外面的def叫函数
在类里面的def叫方法
scala> :paste
// Entering paste mode (ctrl-D to finish)
class HelloWorld{
private var name = "leo"
def sayHello(){print("Hello, "+ name)}
def getName = name
}
// Exiting paste mode, now interpreting.
defined class HelloWorld
scala>
1.2 创建类的对象,并调用方法
scala> val helloworld = new HelloWorld
helloworld: HelloWorld = HelloWorld@2d745993
scala> helloworld.sayHello()
Hello, leo
scala> helloworld.get
getClass getName
scala> helloworld.getName
res41: String = leo
# 如果定义方法时不带括号,则调用方法时也不能带括号
scala> helloworld.getName()
<console>:15: error: not enough arguments for method apply: (index: Int)Char in class StringOps.
Unspecified value parameter index.
helloworld.getName()
^
scala>
1.3 getter与setter
定义不带private的var field,此时scala生成的面向JVM的类时,会定义为private的name字段,并提供public的getter和setter方法。
而如果使用private修饰field,则生成的getter和setter也会private的
如果定义val field,则只会生成getter方法。
如果不希望生成setter和getter方法,则将field声明为private[this]
scala> class Student{
| var name = "leo"
| }
defined class Student
调用getter和setter方法,分别叫做name和name_ =
scala> val s = new Student
s: Student = Student@5d7911d5
#使用getter方法
scala> s.name
res5: String = leo
#使用setter方法
scala> s.name = "jack"
s.name: String = jack
scala> s.name
res6: String = jack
1.4 自定义getter与setter
如果只是希望拥有简单的getter和setter方法,那么就按照scala提供的语法规则,根据需求为field选择合适的修饰符就好:var、val、private、private[this]
但是如果希望能够自己对getter与setter进行控制,则可以自定义getter与sette方法
自定义setter方法的时候一定要注意scala的语法限制,签名、=、参数间不能有空格
主构造函数没有要求传入参数的时候,声明类的时候可以省略括号。
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Student{
private var myName = "leo"
def name = "your name is " + myName
def name_=(newVlaue : String){
print("your cannot edit your name!!!")
}
}
// Exiting paste mode, now interpreting.
defined class Student
scala> val s = new Student
s: Student = Student@73e1ecd0
scala> val s = new Student
s: Student = Student@4b93dd6a
scala> val s = new Student()
s: Student = Student@9d3d54e
scala> s.name
res7: String = your name is leo
scala> s.name = "leo001"
your cannot edit your name!!!s.name: String = your name is leo
scala> s.name
res8: String = your name is leo
1.5 仅暴露field的getter方法
如果你不希望field有setter方法,则可以定义为val,但是此时就再也不能更改field的值了
但是如果希望能够仅仅暴露出一个getter方法,并且还能通过某些方法更改field的值,name需要综合使用private以及自定义getter方法
此时,由于field是private的,所以setter和getter都是private,对外界没有暴露;自己可以实现修改filed值的方法;自己可以覆盖getter方法。
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Student{
private var myname = "leo"
def updatename(newname : String){
if(newname == "leo1") myname = newname
else print("not accept this new name!!!")
}
def name = "your name is " + myname
}
// Exiting paste mode, now interpreting.
defined class Student
scala>
scala> val s = new Student
s: Student = Student@63124022
scala> s.name
res9: String = your name is leo
scala> s.updatename("leo002")
not accept this new name!!!
scala> s.name
res11: String = your name is leo
scala> s.updatename("leo1")
scala> s.name
res13: String = your name is leo1
scala>
1.6 private[this]的使用
如果将field使用private来修饰,那么代表这个field是类私有的,在类的方法中,可以直接访问类的其他对象的private field
这种情况下,如果不希望field被其他对象访问到,那么可以使用private[this],意味着对象私有的field,只能本对象内可以访问到
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Student{
private var myAge = 0
def age_=(newAge : Int){
if(newAge > 0)myAge = newAge
else print("illeagal age!!!")
}
def age = myAge
def older(s:Student) = {
myAge > s.myAge
}
}
// Exiting paste mode, now interpreting.
defined class Student
scala> val s1 = new Student
s1: Student = Student@359e27d2
scala> s1.age = 20
s1.age: Int = 20
scala> val s2 = new Student
s2: Student = Student@574ebdaf
scala> s2.age =25
s2.age: Int = 25
scala> s1.older(s2)
res19: Boolean = false
用 private[this] 声明变量之后,同类之间访问报如下错误:
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Student{
private[this] 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
}
}
// Exiting paste mode, now interpreting.
<console>:26: error: value myAge is not a member of Student
myAge > s.myAge
^
scala>
1.7 Java风格的getter和setter方法
scala的getter和setter方法的命名与java是不同的,是field和field_=的方式
如果要让scala自动生成java风格的getter和setter方法,只要给field添加@BeanProperty注解即可。
此时会生成3个方法,name:String、name_=(newValue : String):Unit、getName():String、setName(newVaule:String)
scala> import scala.beans.BeanProperty
import scala.beans.BeanProperty
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Student{
@BeanProperty var name:String = _
}
// Exiting paste mode, now interpreting.
defined class Student
scala> val s = new Student
s: Student = Student@31533eb1
scala> s.getName()
res20: String = null
scala> s.setName("Leo")
scala> s.getName()
res22: String = Leo
scala>
scala> class Student(@BeanProperty var name:String)
defined class Student
scala> val s = new Student("leo")
s: Student = Student@1926f962
scala> s.getName()
res23: String = leo
scala> s.setName("JACK")
scala> s.getName()
res25: String = JACK
scala>
1.8 辅助constructor
构造函数是初始化实例的,scala中包含主构造函数和辅助构造函数
辅助constructor都是用this这个名称的
第一行如果不互相调用,用this()调用主的constructor
不同辅助constructor传入参数必须不同
scala中,可以给类定义多个辅助constructor,类似于java中的构造函数重载
辅助constructor之间可以互相调用,而且必须第一行调用主constructor
scala> :paste
// Entering paste mode (ctrl-D to finish)
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
}
}
// Exiting paste mode, now interpreting.
defined class Student
scala> val s = new Student
s: Student = Student@4cd8db31
scala> val s2 = new Student("name")
s2: Student = Student@e895e3e
scala> val s3 = new Student("leo",30)
s3: Student = Student@3df3410a
scala>
1.9 主constructor
scala中,主constructor是与类名放在一起的,与java不同
而且类中,没有定义在任何方法或者是代码块之中的代码,就是主constructor的代码,这点感觉没有javaname清晰
在scala中主构造函数是和类名在一起的。
scala> 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("leo",30)
your name is leo ,your age is 30
s: Student = Student@4d75c604
scala>
主constructor中还可以通过使用默认参数,来给参数默认的值
scala> 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
s: Student = Student@114b2414
scala>
如果主constructor传入的参数什么修饰都没有,比如name:String,name如果类内部的方法使用到了,则会声明为private[this] name;否则没有该field,就只能被constructor代码使用而已。
scala> class Student(name:String,age:Int){
| print("-----"+name+"----"+age)
| }
defined class Student
scala> val s = new Student("leo",20)
-----leo----20s: Student = Student@4b7dc788
1.9 内部类
scala中,同样可以在类中定义内部类;但是与java不同的是,每个外部类的对象的内部类,都是不同的类。
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Class{
class Student(val name:String){}
val students = new ArrayBuffer[Student]
def getStudent(name:String) = {
new Student(name)
}
}
// Exiting paste mode, now interpreting.
defined class Class
scala> val c1 = new Class()
c1: Class = Class@5649ec46
scala> val s = cl.getStudent("leo")
<console>:12: error: not found: value cl
val s = cl.getStudent("leo")
^
scala> val s = c1.getStudent("leo")
s: c1.Student = Class$Student@51745f40
scala> c1.students += s
res3: c1.students.type = ArrayBuffer(Class$Student@51745f40)
scala> val c2 = new Class
c2: Class = Class@3c69362a
scala> val s2 = c2.getStudent("jack")
s2: c2.Student = Class$Student@10c07b8d
scala> c1.students += s2
<console>:18: error: type mismatch;
found : c2.Student
required: c1.Student
c1.students += s2
^