object 相当于 class 的单个实例,通常在里面放一些静态的 field 或者 method;在 Scala 中没有静态方法和静态字段,但是可以使用 object 这个语法结构来达到同样的目的。
object 作用:
package com.zy.scala.cls class Session {} object SessionFactory { //该部分相当于 java 中的静态块 val session = new Session //在 object 中的方法相当于 java 中的静态方法 def getSession(): Session = { session } } object SingletonDemo { def main(args: Array[String]) { //单例对象,不需要 new,用【单例对象名称.方法】调用对象中的方法 val session1 = SessionFactory.getSession() println(session1) //单例对象,不需要 new,用【单例对象名称.变量】调用对象中成员变量 val session2 = SessionFactory.session println(session2) } }
如果有一个 class 文件,还有一个与 class 同名的 object 文件,那么就称这个 object是 class 的伴生对象,class 是 object 的伴生类;伴生类和伴生对象必须存放在一个.scala 文件中;伴生类和伴生对象的最大特点是,可以相互访问。
package com.zy.scala.cls //伴生类 class Dog { val id = 1 private var name = "itcast" def printName(): Unit = { //在 Dog 类中可以访问伴生对象 Dog 的私有属性 println(Dog.CONSTANT + name) } } //伴生对象 object Dog { //伴生对象中的私有属性 private val CONSTANT = "汪汪汪 : " def main(args: Array[String]) { val p = new Dog //访问私有的字段 name p.name = "123" p.printName() } }
object 中非常重要的一个特殊方法,就是 apply 方法;
apply 方法通常是在伴生对象中实现的,其目的是,通过伴生类的构造函数功能,来实现伴生对象的构造函数功能;
通常我们会在类的伴生对象中定义 apply 方法,当遇到类名(参数 1,...参数 n)时 apply 方法会被调用;
在创建伴生对象或伴生类的对象时,通常不会使用 new class/class() 的方式,而是直接使用 class(),隐式的调用伴生对象的 apply 方法,这样会让对象创建的更加简洁;
package com.zy.scala.cls /** * Array 类的伴生对象中,就实现了可接收变长参数的 apply 方法, * 并通过创建一个 Array 类的实例化对象,实现了伴生对象的构造函数功能 */ // 指定 T 泛型的数据类型,并使用变长参数 xs 接收传参,返回 Array[T] 数组 // 通过 new 关键字创建 xs.length 长的 Array 数组 // 其实就是调用 Array 伴生类的 constructor 进行 Array 对象的初始化 // def apply[T: ClassTag](xs: T*): Array[T] = { // val array = new Array[T](xs.length) // var i = 0 // for (x <- xs.iterator) { array(i) = x; i += 1 } // array // } object ApplyDemo { def main(args: Array[String]) { //调用了 Array 伴生对象的 apply 方法 //def apply(x: Int, xs: Int*): Array[Int] //arr1 中只有一个元素 5 val arr1 = Array(5) //new 了一个长度为 5 的 array,数组里面包含 5 个 null var arr2 = new Array(5) println(arr1.toBuffer) } }
Scala 中,让子类继承父类,与 Java 一样,也是使用 extends 关键字;
继承就代表,子类可继承父类的 field 和 method ,然后子类还可以在自己的内部实现父类没有的,子类特有的 field 和method,使用继承可以有效复用代码;
子类可以覆盖父类的 field 和 method,但是如果父类用 final 修饰,或者 field 和 method 用 final 修饰,则该类是无法被继承的,或者 field 和 method 是无法被覆盖的。
private 修饰的 field 和 method 不可以被子类继承,只能在类的内部使用;
field 必须要被定义成 val 的形式才能被继承,并且还要使用 override 关键字。 因为 var 修饰的 field 是可变的,在子类中可直接引用被赋值,不需要被继承;即 val 修饰的才允许被继承,var 修饰的只允许被引用。继承就是改变、覆盖的意思。
Java 中的访问控制权限,同样适用于 Scala
|
类内部 |
本包 |
子类 |
外部包 |
|
|
|
|
|
public |
√ |
√ |
√ |
√ |
|
|
|
|
|
protected |
√ |
√ |
√ |
× |
|
|
|
|
|
default |
√ |
√ |
× |
× |
|
|
|
|
|
private |
√ |
× |
× |
× |
|
|
|
|
|
package com.zy.scala.extends_demo class Person { val name = "super" def getName = this.name } class Student extends Person { //继承加上关键字 override val name = "sub" //子类可以定义自己的field和method val score = "A" def getScore = this.score }
Scala中override 和 super 关键字
package com.zy.scala.extends_demo class Person1 { private val name = "leo" val age = 50 def getName = this.name } class Student extends Person1 { private val score = "A" //子类可以覆盖父类的 val field,使用override关键字 override val age = 30 def getScore = this.score //覆盖父类非抽象方法,必须要使用 override 关键字 //同时调用父类的方法,使用super关键字 override def getName = "your name is " + super.getName }
Scala中isInstanceOf 和 asInstanceOf
如果实例化了子类的对象,但是将其赋予了父类类型的变量,在后续的过程中,又需要将父类类型的变量转换为子类类型的变量,应该如何做?
Scala |
Java |
obj.isInstanceOf[C] |
obj instanceof C |
obj.asInstanceOf[C] |
(C)obj |
classOf[C] |
C.class |
package com.zy.scala.extends_demo class Person3 {} class Student3 extends Person3 object Student3 { def main(args: Array[String]) { val p: Person3 = new Student3 var s: Student3 = null //如果对象是 null,则 isInstanceOf 一定返回 false println(s.isInstanceOf[Student3]) // 判断 p 是否为 Student3 对象的实例 if (p.isInstanceOf[Student3]) { //把 p 转换成 Student3 对象的实例 s = p.asInstanceOf[Student3] } println(s.isInstanceOf[Student3]) } }
Scala中getClass 和 classOf
package com.zy.scala.extends_demo class Person4 {} class Student4 extends Person4 object Student4 { def main(args: Array[String]) { val p: Person4 = new Student4 //判断p是否为Person4类的实例 println(p.isInstanceOf[Person4]) //true //判断p的类型是否为Person4类 println(p.getClass == classOf[Person4]) //false //判断p的类型是否为Student4类 println(p.getClass == classOf[Student4]) //true } }
Scala中使用模式匹配进行类型判断
package com.zy.scala.extends_demo class Person5 {} class Student5 extends Person5 object Student5 { def main(args: Array[String]) { val p: Person5 = new Student5 p match { // 匹配是否为Person类或其子类对象 case per: Person5 => println("This is a Person5's Object!") // 匹配所有剩余情况 case _ => println("Unknown type!") } } }
Scala中protected
package com.zy.scala.extends_demo class Person6 { protected var name: String = "tom" protected[this] var hobby: String = "game" protected def sayBye = println("再见...") } class Student6 extends Person6 { //父类使用protected 关键字来修饰 field可以直接访问 def sayHello = println("Hello " + name) //父类使用protected 关键字来修饰method可以直接访问 def sayByeBye = sayBye def makeFriends(s: Student6) = { println("My hobby is " + hobby + ", your hobby is UnKnown") } } object Student6 { def main(args: Array[String]) { val s: Student6 = new Student6 s.sayHello s.makeFriends(s) s.sayByeBye } }
Scala中调用父类的constructor
package com.zy.scala.extends_demo class Person7(val name: String, val age: Int) { var score: Double = 0.0 var address: String = "beijing" def this(name: String, score: Double) = { //每个辅助constructor的第一行都必须调用其他辅助constructor或者主constructor代码 //主constructor代码 this(name, 30) this.score = score } //其他辅助constructor def this(name: String, address: String) = { this(name, 100.0) this.address = address } } class Student7(name: String, score: Double) extends Person7(name, score)
Scala中匿名内部类
package com.zy.scala.extends_demo class Person8(val name: String) { def sayHello = "Hello ,I'm " + name } class GreetDemo { //接受Person8参数,并规定Person8类只含有一个返回String的sayHello方法 def greeting(p: Person8 { def sayHello: String}) = { println(p.sayHello) } } object GreetDemo { def main(args: Array[String]) { //创建Person8的匿名子类对象 val p = new Person8("tom") val g = new GreetDemo g.greeting(p) } }
package com.zy.scala.extends_demo abstract class Person9(val name: String) { //必须指出返回类型,不然默认返回为Unit def sayHello: String def sayBye: String } class Student9(name: String) extends Person9(name) { //必须指出返回类型,不然默认 def sayHello: String = "Hello," + name def sayBye: String = "Bye," + name } object Student9 { def main(args: Array[String]) { val s = new Student9("tom") println(s.sayHello) println(s.sayBye) } }
Scala中抽象field
package com.zy.scala.extends_demo abstract class Person10 (val name:String){ //抽象fields val age:Int } class Student10(name: String) extends Person10(name) { val age: Int = 50 }
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。