1. 类
1.1. 类的定义
package cn.toto.scala.day2
/**
* 在Scala中,类并不用声明为public类型的。
* Scala源文件中可以包含多个类,所有这些类都具有共有可见性。
* Created by toto on 2017/6/29.
*/
class Person {
//用val修饰的变量是可读属性,有getter但没有setter(相当与Java中用final修饰的变量)
val id = "9527"
//用var修饰的变量都既有getter,又有setter
var age : Int = 18
//类私有字段,只能在类的内部使用
private var name : String = "toto"
//对象私有字段,访问权限更加严格的,Person类的方法只能访问到当前对象的字段
//在伴生对象里面也不可以访问,这里相当于是java中private的,没有getter和setter的方法
private[this] var pet = "小强"
def sayHi() : Unit = {
//下面的运行结果是:9527
println(id)
//下面的结果是:18
println(age)
//说明在自己的类中可以访问到,下面的运行结果是:toto
println(name)
//说明只有在类里面可以访问到private[this]类型的变量,下面的运行结果是"小强",说明已经被修改了。
println(pet)
}
}
/**
* 这个名字和类名相同,叫伴生对象
*/
object Person {
//在伴生变量中定义的变量相当于就是静态变量
var i = 1
//在伴生变量中定义的方法相当于是静态方法
def main(args: Array[String]): Unit = {
//结果是:1
println(i)
val p = new Person()
//如果是下面的修改,发现下面有红线,说明val类型的不支持重新赋值
//p.id = "123"
//下面的结果是:9527
println(p.id)
//下面的结果是:18
println(p.age)
p.age = 27
//下面的结果是:27
println(p.age)
//下面的结果是:唐伯虎
println(p.name)
p.name = "toto"
//这里说明可以在伴生对象中访问到私有的变量
//下面的结果是:toto
println(p.name)
p.sayHi()
}
}
object Test {
def main(args: Array[String]): Unit = {
var p = new Person()
//运行结果是18
println(p.age)
//运行结果是:9527
println(p.id)
/**
* 下面的运行结果是:
* 9527
* 18
* 唐伯虎
* 小强
*/
p.sayHi()
//这里不可以直接通过p.pet访问到。
//这里面也不可以访问到p.name
}
}
1.2. 构造器
注意:主构造器会执行类定义中的所有语句
package cn.toto.scala.day2
import java.io.IOException
/**
* Created by toto on 2017/6/29.
*
* 构造器参数可以不带val或var,如果不带val或var的参数至少被一个方法所使用
* 那么它将被提升为字段
*
* 跟类名交织在一起的叫 主构造器
* val定义的只能读不能改(成员变量)
* var 可以读,有了默认值,在传参的时候,可以不传参了。
* faceValue :可以通过这个为它初始赋值,有了默认值,可以不传参了,相当于private[this],只能在类的内部使用
*/
class Student(val name : String,
var age:Int,
faceValue:Double = 99.9,
private var height : Int = 18) {
//主构造器会执行类定义中的所有语句
println("执行主构造器")
//faceValue被下面的方法使用后,faceValue就变成了不可变的对象私有字段了,等同于private[this] val faceValue
//如果没有被方法使用该参数将不被保存为字段,仅仅是一个可以被主构造器中的代码访问的普通参数
def description = name + " is " + age + " years old,颜值是:" + faceValue
//定义为辅构造函数用
private[this] var gender : String = null
try {
println("读取文件");
throw new IOException("io exception");
} catch {
case e:NullPointerException => println("打印异常Exception:" + e)
case e:IOException => println("打印异常Exception:" + e)
}
def show() : Unit = {
//faceValue = 1000
println(faceValue)
}
//用this关键字定义辅助构造器
//辅助构造器 def this (参数)
def this(name : String,age : Int,gender: String) {
//每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始
//第一行必须先调用主构造器
this(name,age)
println("执行辅助构造器")
println("faceValue:" + this.faceValue)
println("height:" + this.height)
//对于没法在主构造器中定义的变量,可以定义一个私有字段
this.gender = gender
println("gender:" + this.gender)
}
}
object Student {
def main(args: Array[String]): Unit = {
/**
* 私有的构造器,只有在其伴生对象中使用
*
* 下面立即执行出结果:
* 执行主构造器
* 读取文件
* 打印异常Exception:java.io.IOException: io exception
*/
val p = new Student("toto", 27, 100, 180)
//运行结果是:27
println(p.age)
//运行结果是:toto
println(p.name)
p.age = 18
p.height = 199;
//运行结果是:18
println(p.age)
//运行结果是:199
println(p.height)
//运行对的结果是:toto is 18 years old,颜值是:100.0
println(p.description)
var per = new Person
println(per)
}
}
object Main {
def main(args: Array[String]): Unit = {
/**
* 理解执行出结果:
* 执行主构造器
* 读取文件
* 打印异常Exception:java.io.IOException: io exception
*/
val stu1 = new Student("toto",30)
//只是:toto,说明调用的不是辅助构造器
println(stu1.name)
/**
* 调用的时候就立即显示:
* 执行主构造器
* 读取文件
* 打印异常Exception:java.io.IOException: io exception
* 执行辅助构造器
* faceValue:99.9
* height:18
* gender:男
*/
var stu2 = new Student("toto",27,"男")
println(stu2.age)
println(stu2.name)
//下面的取不到
//println(stu2.height)
//下面的也获取不到
//println(faceValue);
}
}
1.3. 单例对象
在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的
1.存放工具方法和常量
2.高效共享单个不可变的实例
3.单例模式
package cn.toto.scala.day2
import scala.collection.mutable.ArrayBuffer
object SingletonDemo {
def main(args: Array[String]) {
//单例对象,不需要new,用【类名.方法】调用对象中的方法
val session = SessionFactory.getSession()
//获得结果:cn.toto.scala.day2.Session@96532d6
println(session)
}
}
object SessionFactory {
//该部分相当于java中静态块
var counts = 5
val sessions = new ArrayBuffer[Session]()
while(counts > 0) {
sessions += new Session
counts -= 1
}
//在object中的方法相当于java中的静态方法
def getSession() : Session = {
sessions.remove(0)
}
}
class Session {}
在如:
package cn.toto.scala.day2
/**
* Created by toto on 2017/6/29.
*/
class SingletonDemo2 {
println("abc")
SingletonDemo2.sayHi()
SingletonDemo2
test()
def test() : Unit = {
println("test")
}
}
object SingletonDemo2 {
private val t = 123
def sayHi() : Unit = {
println("hi ~")
}
/**
* 运行的结果是:
* hi ~
* 123
* 123
* abc
* hi ~
* test
* hi ~
* ()
* cn.toto.scala.day2.SingletonDemo2$@5e025e70
* cn.toto.scala.day2.SingletonDemo2$@5e025e70
* cn.toto.scala.day2.SingletonDemo2$@5e025e70
*/
def main(args: Array[String]): Unit = {
sayHi()
println("123")
println(t)
val s = new SingletonDemo2
val s1 = SingletonDemo2.sayHi()
println(s1)
val s2 = SingletonDemo2
val s3 = SingletonDemo2
println(s3)
println(s3)
val s4 = SingletonDemo2
println(s4)
}
}
1.4. 伴生对象
在Scala的类中,与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性
package cn.toto.scala.day2
/**
* Created by toto on 2017/6/29.
*/
class Dog {
val id = 1
private var name = "toto"
def printName() : Unit = {
//在Dog类中可以访问伴生对象Dog的私有属性
println(Dog.CONSTANT + name)
}
}
object Dog {
//伴生对象中的私有属性
private val CONSTANT = "汪汪汪 : "
/**
* 运行结果是:
* 汪汪汪 : toto
* 汪汪汪 : 123
* @param args
*/
def main(args:Array[String]): Unit = {
val p = new Dog
//访问私有字段name
p.printName()
p.name = "123"
p.printName()
}
}
1.5. apply方法
通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,…参数n)时apply方法会被调用
package cn.toto.scala.day2
/**
* Created by toto on 2017/6/30.
*/
object ApplyDemo {
def main(args: Array[String]): Unit = {
//調用了Array半生对象的apply方法
//def apply(x:Int,xs:Int*):Array[Int]
//arr1中只有一个元素5
var arr1 = Array(5)
println(arr1.toBuffer)
//new了一个长度为5的array,数组里面包含5个null
var arr2 = new Array(5)
}
}
在如:
package cn.toto.scala.day2
/**
* Created by toto on 2017/6/30.
*/
object ApplyDemo {
def apply() : Unit = {
println("apply invoked")
}
def apply(name:String):String = {
name
}
def apply(name:Int) : Int = {
println("Int")
name
}
/**
* 从下面的案例中可以知道,若没有使用new关键字创建实例,它将使用相应的apply方法来创建实例
* @param args
*/
def main(args: Array[String]): Unit = {
// //运行结果是:apply invoked
// val a1 = ApplyDemo()
结果直接是tom
//val a2 = ApplyDemo("tom")
//结果是:Int
val a3 = ApplyDemo(10)
//打印的结果是:10
println(a3)
}
}
1.6. 应用程序对象
Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。
package cn.toto.scala.day2
/**
* Created by toto on 2017/6/30.
* //运行结果是:I love you Scala
*/
object AppObjectDemo extends App{
//不用写main方法
println("I love you Scala")
}