购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.5 类和对象

1.5.1 类的定义

我们已经知道,对象是类的具体实例,类是抽象的,不占用内存,而对象是具体的,占用存储空间。

Scala中一个简单的类定义是使用关键字class,类名必须大写。类中的方法用关键字def定义,例如以下代码:

如果一个类不写访问修饰符,那么默认访问级别为Public,这与Java是不一样的。

关键字new用于创建类的实例。例如,调用上述代码中的count()方法,可以使用以下代码:

new User().count()

1.5.2 单例对象

Scala中没有静态方法或静态字段,但是可以使用关键字object定义一个单例对象,单例对象中的方法相当于Java中的静态方法,可以直接使用“单例对象名.方法名”方式进行调用。单例对象除了没有构造器参数外,可以拥有类的所有特性。

例如以下代码定义了一个单例对象Person,该对象中定义了一个方法showInfo():

可以在任何类或对象中使用代码Person.showInfo()对方法showInfo()进行调用。

1.5.3 伴生对象

当单例对象的名称与某个类的名称一样时,该对象被称为这个类的伴生对象。类被称为该对象的伴生类。

类和它的伴生对象必须定义在同一个文件中,且两者可以互相访问其私有成员。例如以下代码:

运行上述伴生对象Person的main方法,输出结果如下:

姓名:zhangsan
年龄:20

1.5.4 get和set方法

Scala默认会根据类的属性的修饰符生成不同的get和set方法,生成原则如下:

● val修饰的属性,系统会自动生成一个私有常量属性和一个公有get方法。

● var修饰的属性,系统会自动生成一个私有变量和一对公有get/set方法。

● private var修饰的属性,系统会自动生成一对私有get/set方法,相当于类的私有属性,只能在类的内部和伴生对象中使用。

● private[this]修饰的属性,系统不会生成get/set方法,即只能在类的内部使用该属性。

例如有一个Person类,代码如下:

class Person {
  val id:Int=10
  var name="zhangsan"
  private var gender:Int=0
  private[this] var age:Int=20
}

将该类编译为class文件后,再使用Java反编译工具将其反编译为Java代码,代码如下:

使用name属性举例,在Scala中,get和set方法并非被命名为getName和setName,而是被命名为name和name_=,由于JVM不允许在方法名中出现=,因此=被翻译成$eq。

从上述代码可以看出,由于属性id使用val修饰,因此不可修改,只生成了与get方法对应的id();属性name使用var修饰,因此生成了与get和set方法对应的name()和name_$eq()方法,且都为public;属性gender由于使用private var修饰,因此生成了private修饰的get和set方法;属性age由于使用private[this]修饰,因此没有生成get和set方法,只能在类的内部使用。

此时可以使用如下代码对Person类中的属性进行访问:

除了系统自动生成get和set方法外,也可以手动进行编写,例如以下代码:

当然也可以使用如下Java风格定义get和set方法:

1.5.5 构造器

Scala中的构造器分为主构造器和辅助构造器。

1.主构造器

主构造器的参数直接放在类名之后,且将被编译为类的成员变量,其值在初始化类时传入。例如以下代码:

可以通过对主构造器的参数添加访问修饰符来控制参数的访问权限。例如以下代码,将参数age设置为私有的,参数name设置为不可修改(val):

class Person(val name:String, private var age:Int) {
}

构造参数也可以不带val或var,此时默认为private[this] val,代码如下:

class Person(name:String,age:Int) {
}

在主构造器被执行时,类定义中的所有语句同样会被执行。例如以下代码中的println语句是主构造器的一部分,每当主构造器被执行时,该部分代码同样会被执行,可以在这里做一些类的初始化工作:

class Person(var name:String,var age:Int) {
  println(name)
  println(age)
  //初始化语句...
}

如果需要将整个主构造器设置为私有的,那么只需要添加private关键字即可,例如以下代码:

class Person private(var name:String,var age:Int) {
}

注意,主构造器也可以没有参数,一个类中如果没有显式地定义主构造器,就默认有一个无参构造器。

2.辅助构造器

Scala类除了可以有主构造器外,还可以有任意多个辅助构造器。辅助构造器的定义需要注意以下几点:

● 辅助构造器的方法名称为this。

● 每一个辅助构造器的方法体中必须首先调用其他已定义的构造器。

● 辅助构造器的参数不能使用var或val进行修饰。

例如以下代码定义了两个辅助构造器:

上述构造器可以使用如下3种方式进行调用:

var per1=new Person                  //调用无参主构造器
var per2=new Person("lisi")          //调用辅助构造器一
var per3=new Person("lisi",28) //调用辅助构造器二

除此之外,主构造器还可以与辅助构造器同时使用,在这种情况下,一般辅助构造器的参数要多于主构造器,代码如下:

上述代码运行的输出结果为: 1RAQju+Y5Jw906MtWSO/cZyRrIeA6ysRgKn+0dDLwOLVBdmIxhVTmtohHk1VRyNN

zhangsan
20
male
点击中间区域
呼出菜单
上一章
目录
下一章
×