yunfenglee 2020-05-30
Object
在scala中被object关键字修饰的类有如下特征:
1、是单例的
2、不需要通过new来创建对象,直接通过类名创建
3、没有有参的主构造器,但是有主构造代码块(不包含在任何方法中的代码,就是object的主构造代码块)
4、通常用于封装一些常量、工具类、枚举和隐式转换函数
5、主构造代码块只会执行一次,因为是单例的
object ObjectDemo { println("ObjectDemo 的主构造代码块") def sayHello = println("hello world") println("ObjectDemo 的主构造代码块2") } object ObjectDemo2 { def main(args: Array[String]): Unit = { val obj1 = ObjectDemo val obj2 = ObjectDemo println(obj1.hashCode() == obj2.hashCode()) } } 运行结果: ObjectDemo 的主构造代码块 ObjectDemo 的主构造代码块2 true
object.apply方法
package clazz object ObjectDemo_02 { println("hello world") def apply() = { println("hello") } def apply(nums: Int*): Array[Int] = { val arr = new Array[Int](nums.length) for (i <- 0 to nums.length - 1) arr(i) = nums(i) arr } } object ObjectDemo_0201 { def main(args: Array[String]): Unit = { //创建了一个ObjectDemo_02对象 val o = ObjectDemo_02 println("----------------") //创建了一个ObjectDemo_02对象,并且调用了无参的apply方法 val o1 = ObjectDemo_02() println("----------------") //创建了一个ObjectDemo_02对象,并且调用了有参的apply方法 val o2 = ObjectDemo_02(1, 2, 2, 3) //ObjectDemo_02(1, 2, 2, 3) 等同于显示调用 ObjectDemo_02.apply(1,2,2,3) o2.foreach(println(_)) } } 运行结果: hello world ---------------- hello ---------------- 1 2 2 3
伴生类与伴生对象
?* 伴生类和伴生对象一定要在同一个类文件中,并且类名相同
?* 伴生类和伴生对象的特点是可以相互访问被private修饰的字段
//伴生类 class MyArray { private var name: String = "小明" println(MyArray.name) } //伴生对象 object MyArray { private var name: String = "小红" println(new MyArray().name) def apply(nums: Int*): Array[Int] = { val arr = new Array[Int](nums.length) for (i <- 0 to nums.length - 1) arr(i) = nums(i) arr } } object ObjectDemo_03 { def main(args: Array[String]): Unit = { //类比数组的创建方式 var arr = Array(1, 2, 3) //通过伴生对象和有参的apply方法创建对象 var arr2 = new Array[Int](5) //通过伴生类创建对象 var arr3 = MyArray(1, 2, 3) println("------") var arr4 = new MyArray() } } 运行结果: 小红 小明 ------ 小红
object继承App,App内部有个main方法,object不用main也可执行。
object ObjectDemo_04 extends App { println("hello") }
object枚举
伴生对象继承Enumeration
object MyEnum extends Enumeration { //方式1 // val RED, GREEN, YELLOW = Value //方式2 val RED2 = Value(0, "red2") val GREEN2 = Value(1, "green2") val YELLOW2 = Value(2, "yellow2") } object ObjectDemo_05 { def main(args: Array[String]): Unit = { // println(MyEnum.GREEN) //通过枚举角标获取枚举值 println(MyEnum(0)) //通过枚举名称获取枚举值 println(MyEnum.withName("green2")) println("----") //获取所有的枚举值 val vs = MyEnum.values for (i <- vs) println(i) } }
外部类与内部类
?* 每个外部类的实例所持有的内部类都是不同的类!!!
class Person { //内部类 class Student def getStu: Student = { new Student } val lb = ListBuffer[Student]() } object ObjectDemo_06 { def main(args: Array[String]): Unit = { val p1 = new Person val stu1: p1.Student = p1.getStu //类型为:p1.Student p1.lb += stu1 val p2 = new Person val stu2: p2.Student = p2.getStu //类型为:p2.Student p2.lb += stu2 } }
扩大内部类的作用域
package clazz import scala.collection.mutable.ListBuffer class Person { //内部类 class Student def getStu: Student = { new Student } //通过外部类的类型投影,扩大内部类的影响范围 //ListBuffer 容器可以放多个外部类的实例所持有的内部类对象了 val lb = ListBuffer[Person#Student]() } object ObjectDemo_06 { def main(args: Array[String]): Unit = { //扩大内部类的影响范围----1、类型投影----2、内部类放在伴生对象中,实现单例 val p3 = new Person val stu3: p3.Student = p3.getStu //类型为:p1.Student val p4 = new Person val stu4: p4.Student = p4.getStu //类型为:p2.Student p3.lb += stu3 p3.lb += stu4 println(p3.lb.size) //2 } }
case class
样例类:与普通类基本一致,只是可以不使用new来创建对象
case class Student(var name:String,var age:Int) { println(s"hello,I am $name, $age years old") } object ObjectDemo_07 { def main(args: Array[String]): Unit = { val s1 = Student("小明",12) val s2 = new Student("小王",10) } }