面向对象
类class
Scala 2中的类class
和Java中的类
,概念是相似的。
创建类
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Person {
var name = "lixingyun"
// 定义方法时如果有(),那么调用时()可有可无
def hello() {
println("hello, " + name)
}
// 定义方法时如果没有(),那么调用时()就不能有
def getName = name
}
// Exiting paste mode, now interpreting.
defined class Person
scala> val person = new Person()
person: Person = Person@4f3e7344
// 调用方法可以不带()
scala> person.hello
hello, lixingyun
scala> person.getName
res0: String = lixingyun
// 调用没有()的方法,指定()会报错
scala> person.getName()
<console>:13: error: not enough arguments for method apply: (index: Int)Char in class StringOps.
Unspecified value parameter index.
person.getName()
构造函数
Scala 2的构造函数分为两种。
主构造函数
:类似于Java的默认构造函数this()
,主构造函数
是与类名放在一起的,而且它不会定义在任何方法或是代码块中。
scala> :paste
// Entering paste mode (ctrl-D to finish)
// 可以设置默认参数
class User(val name: String = "lixingyun", val age: Int = 22) {
// 这就是主构造函数
println(name + ", " + age)
}
// Exiting paste mode, now interpreting.
defined class User
scala> new User("lixingyun", 22)
lixingyun, 22
res0: User = User@340afaf8
scala> new User("wanglin")
wanglin, 22
res1: User = User@59696551
// 通过带名参数的方式调用
scala> new User(age = 21, name = "xiaoyan")
xiaoyan, 21
res2: User = User@68ef01a5
辅构造函数
:类似于Java的重载构造函数this(name, age)
,辅构造函数
可以有多个。辅构造函数
之间可以互相调用,但第一行必须调用主构造函数
。
scala> :paste
// Entering paste mode (ctrl-D to finish)
class User {
var name = "lixingyun"
var age = 22
// 辅构造函数1
def this(name: String) {
this()
this.name = name
}
// 辅构造函数2
def this(name: String, age: Int) {
this(name: String)
this.name = name
this.age = age
}
}
// Exiting paste mode, now interpreting.
defined class User
scala> val user = new User("lixingyun")
user: User = User@47fbc56
scala> val user = new User("lixingyun", 22)
user: User = User@47be0f9b
对象object
Scala 2中的对象object
既可以单独定义,也可以用new
创建。
这个定义出来的object
相当于是class
的单个实例,通常在里面放一些静态的成员变量或方法,它不能new
,但可以直接使用。
且object
不能定义有参数的构造器,只能定义无参构造器。
第一次调用object
方法时,会执行它的构造方法,但仅执行一次(这个特性比较有用)。
scala> :paste
// Entering paste mode (ctrl-D to finish)
object User {
var name = "lixingyun"
var age = 22
// 无参构造函数
println("this is lixingyun")
// 定义构造函数
def getName = name
def getAge = age
}
// Exiting paste mode, now interpreting.
defined object User
// 第一次调用时执行,仅执行一次
scala> val name = User.getName
this is lixingyun
name: String = lixingyun
scala> val age = User.age
age: Int = 22
伴生对象和伴生类
如果已经定义了一个class
,还有一个与class
同名的object
,那么这个object
就是这个class
的伴生对象
,class
则称为这个object
的伴生类
。
伴生对象
和伴生类
必须存放在一个.scala
文件中。
伴生对象
和伴生类
的最大特点在于它们之间可以互相访问对方的private
方法,也就是私有方法(有点像夫妻之间干的事)。
scala> :paste
// Entering paste mode (ctrl-D to finish)
object User {
private val name1 = "lixingyun"
private val age1 = 22
println("this is lixingyun")
// 定义构造函数
def getName = name1
def getAge = age1
}
class User(val name2: String, val age2: Int) {
// 直接调用伴生对象的私有方法
def hello = println("name2 = " + name2 + ", age2 = " + age2 + "; name1 = " + User.name1 + ", age1 = " + User.age1)
}
// Exiting paste mode, now interpreting.
defined object User
defined class User
scala> val user = new User("wanglin", 20)
user: User = User@6a9b9909
scala> user.hello
this is lixingyun
name2 = wanglin, age2 = 20; name1 = lixingyun, age1 = 22
// 对象自身都是无法直接访问私有成员变量的,但伴生类却可以
scala> User.name1
<console>:13: error: value name1 is not a member of object User
User.name1
^
scala> User.getName
res2: String = lixingyun
apply()方法
这是object
中比较重要的一个特殊方法,通常在伴生对象
中实现apply()
方法,并在其其中实现构造伴生类对象的功能。
有了apply()
方法,类就不用再通过new
来创建对象了,而可以使用Class()
的方式,隐式调用伴生对象的apply()
方法生成对象。
Array对象的源码中就有apply()
方法的应用。
object Array extends FallbackArrayBuilding {
......
/** Creates an array with given elements.
*
* @param xs the elements to put in the array
* @return an array containing all elements from xs.
*/
// Subject to a compiler optimization in Cleanup.
// Array(e0, ..., en) is translated to { val a = new Array(3); a(i) = ei; a }
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
}
/** Creates an array of `Boolean` objects */
// Subject to a compiler optimization in Cleanup, see above.
def apply(x: Boolean, xs: Boolean*): Array[Boolean] = {
val array = new Array[Boolean](xs.length + 1)
array(0) = x
var i = 1
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
/** Creates an array of `Byte` objects */
// Subject to a compiler optimization in Cleanup, see above.
def apply(x: Byte, xs: Byte*): Array[Byte] = {
val array = new Array[Byte](xs.length + 1)
array(0) = x
var i = 1
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
/** Creates an array of `Short` objects */
// Subject to a compiler optimization in Cleanup, see above.
def apply(x: Short, xs: Short*): Array[Short] = {
val array = new Array[Short](xs.length + 1)
array(0) = x
var i = 1
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
/** Creates an array of `Char` objects */
// Subject to a compiler optimization in Cleanup, see above.
def apply(x: Char, xs: Char*): Array[Char] = {
val array = new Array[Char](xs.length + 1)
array(0) = x
var i = 1
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
/** Creates an array of `Int` objects */
// Subject to a compiler optimization in Cleanup, see above.
def apply(x: Int, xs: Int*): Array[Int] = {
val array = new Array[Int](xs.length + 1)
array(0) = x
var i = 1
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
/** Creates an array of `Long` objects */
// Subject to a compiler optimization in Cleanup, see above.
def apply(x: Long, xs: Long*): Array[Long] = {
val array = new Array[Long](xs.length + 1)
array(0) = x
var i = 1
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
/** Creates an array of `Float` objects */
// Subject to a compiler optimization in Cleanup, see above.
def apply(x: Float, xs: Float*): Array[Float] = {
val array = new Array[Float](xs.length + 1)
array(0) = x
var i = 1
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
/** Creates an array of `Double` objects */
// Subject to a compiler optimization in Cleanup, see above.
def apply(x: Double, xs: Double*): Array[Double] = {
val array = new Array[Double](xs.length + 1)
array(0) = x
var i = 1
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
/** Creates an array of `Unit` objects */
def apply(x: Unit, xs: Unit*): Array[Unit] = {
val array = new Array[Unit](xs.length + 1)
array(0) = x
var i = 1
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
......
}
下面自定义一个有apply()
方法的伴生对象
及其对应的伴生类
。
scala> :paste
// Entering paste mode (ctrl-D to finish)
class User(val name: String) {
println("class User name = " + name)
}
object User {
def apply(name: String) = {
println("apply object User name = " + name)
new User(name)
}
}
// Exiting paste mode, now interpreting.
defined class User
defined object User
// 调用伴生对象的apply()方法生成对象
scala> User("lixingyun")
apply object User name = lixingyun
class User name = lixingyun
res0: User = User@102efc59
// 不使用伴生对象生成对象
scala> new User("wanglin")
class User name = wanglin
res1: User = User@6242ae3b
个人觉得在开发中保持一种风格就行了。比如按照new
的方法来生成对象,这样不管Java还是Scala 2都能保持统一。
所以从这个意义上来说,apply()
方法其实没什么用。
main()方法
和Java一样,Scala 2应用程序也需要一个入口
,这个入口
就是main()
方法。
main()
方法必须定义在object
中。
package com.itechthink
/**
* 创建一个object
*
*/
object HelloScala {
def main(args: Array[String]): Unit = {
println("Hello Scala")
}
}
接口trait
extend
关键字对于继承class
还是trait
,都是通用的,而实现trait
时不需要像Java那样使用override
关键字。
package com.itechthink
/**
* 接口多重继承
*
*/
object MultipleInheritance {
def main(args: Array[String]): Unit = {
val user = new User("李星云")
user.fight()
user.helpWeakness(new User("王林"))
}
}
/**
* 功夫接口
*
*/
trait KongFu {
// 格斗
def fight(): Unit
}
/**
* 行侠仗义接口
*
*/
trait JusticeToHelpWeakness {
// 仗义援手
def helpWeakness(user: User): Unit
}
class User(val name: String) extends KongFu with JusticeToHelpWeakness {
// 实现fight()方法
def fight(): Unit = {
println(name + " 展开了攻击")
}
// 实现helpWeakness()方法,override有也可以,没有也行
override def helpWeakness(user: User): Unit = {
println(name + " 帮助了 " + user.name)
}
}
感谢支持
更多内容,请移步《超级个体》。