1 类与对象
- 创建类的语法格式
class ClassName[parameterList]
- 创建对象的语法格式
ClassName objectName = new ClassName();
例1:定义一个Point类
class Point(a: Int, b: Int) {
var x = a
var y = b
def move(dx: Int, dy: Int): Unit = {
x += dx
y += dy
println("x: " + x)
println("y: " + y)
}
}
object PointTest {
def main(args: Array[String]): Unit = {
val point = new Point(2, 3)
point.move(10, 21)
}
}
2 构造器
例1也可以取消参数列表,改写成有构造器
class Point {
var x = 0
var y = 0
def this(a: Int, b: Int) {
this()
x = a
y = b
}
def move(dx: Int, dy: Int): Unit = {
x += dx
y += dy
println("x: " + x)
println("y: " + y)
}
}
例2:自定义计数器,使用多重构造器
class Counter {
private var value = 0
private var name = "Default"
private var mode = 0
def this(name: String) {
this()
this.name = name
}
def this(name: String, mode: Int) {
this(name)
this.mode = mode
}
def increment(step: Int): Unit = value += step
def current(): Int = value
def info(): Unit = {
printf("Name: %s, Mode: %d\n", name, mode)
}
}
object CounterTest {
def main(args: Array[String]): Unit = {
val myCounter = new Counter
val runnerCounter = new Counter("Runner")
val timerCounter = new Counter("Timer", 2)
myCounter.info
myCounter.increment(1)
println(myCounter.current())
runnerCounter.info
runnerCounter.increment(2)
println(runnerCounter.current())
timerCounter.info()
timerCounter.increment(3)
println(timerCounter.current())
}
}
3 get和set
class Counter {
private var privateValue = 0
// scala的get方法
def value = privateValue
// scala的set方法
def value_=(newValue: Int): Unit = {
if (newValue > 0) privateValue = newValue
}
def increment(step: Int): Unit = value += step // 只有一行可以去掉大括号
def increment(): Unit = value += 1
def current(): Int = value // 把value作为返回值
}
object CounterTest {
def main(args: Array[String]): Unit = {
val myCounter = new Counter
// 调用无参数increment
myCounter.increment
println(myCounter.current)
// 调用set方法
myCounter.value = 2
// 调用get方法
println(myCounter.value)
// 调用有参数increment
myCounter.increment(2)
println(myCounter.current)
}
}
4 单例对象与伴生对象
- 单例对象
object Hello {
def main(args: Array[String]): Unit = {
println("Hello World!")
}
}
- 伴生对象
class Person {
private val id = Person.newPersonId()
private var name = ""
def this(name: String) {
this()
this.name = name
}
def info() {printf("The id of %d is %s.\n", id, name)}
}
// 与class同名的object 则该object是同名class的伴生对象
object Person {
private var lastId = 0
// 反编译后可知这是一个static方法
private def newPersonId() = {
lastId += 1
lastId
}
def main(args: Array[String]): Unit = {
val p1 = new Person("Ziyu")
val p2 = new Person("Minxing")
p1.info()
p2.info()
}
}
5 Apply方法
apply方法自动调用
class ApplyTest {
def apply() {
println("apply method in class is called!")
}
def greetingOfClass: Unit = {
println("Greeting method in class is called!")
}
}
object ApplyTest {
def apply(): ApplyTest = {
println("apply method in object is called!")
new ApplyTest()
}
def main(args: Array[String]): Unit = {
// 调用伴生对象的apply方法,返回一个伴生类的对象
val a = ApplyTest()
a.greetingOfClass
// a已经是实例对象,调用伴生类的apply方法
a()
// b本来就是实例对象
val b = new ApplyTest
b()
}
}
- Array的apply方法
val myArr = Array("Hadoop")
// ctrl 点击Array进去有新发现
// object Array 下的 apply 方法
def apply[T: ClassTag](xs: T*): Array[T] = {
val len = xs.length
xs match {
case wa: mutable.WrappedArray[_] if wa.elemTag == classTag[T] =>
// We get here in test/files/run/sd760a.scala, `Array[T](t)` for
// a specialized type parameter `T`. While we still pay for two
// copies of the array it is better than before when we also boxed
// each element when populating the result.
ScalaRunTime.array_clone(wa.array).asInstanceOf[Array[T]]
case _ =>
val array = new Array[T](len)
var i = 0
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
}
// 可以看到新建了一个array类的实例对象并返回给myArr
6 Update方法
object TestUpdateClass {
def main(args: Array[String]): Unit = {
val myArr = Array(1, 2, 3)
// 调用myArr.update(0, 0)
myArr(0) = 0
}
}
现在可以初步理解为什么scala数组访问用圆括号了
7 抽象类
- 变量可以没有定义
- 方法可以没有定义
abstract class car {
val carBand: String
def info()
def greeting(): Unit = {
println("Welcome to my car!")
}
}
8 继承
接上一节抽象类
class BMWcar extends car {
// 这个override可以没有,因为父类没有给出变量定义
override val carBand: String = "BMO"
// 父类没有给方法定义,所以可以不用override
def info(): Unit = {
printf("This is a %s car.\n", carBand)
}
// 重写父类方法需要用override
override def greeting(): Unit = {
println("Welcome to my BMW car! It is cheap!")
}
}
class BYDcar extends car {
override val carBand: String = "BYD"
def info(): Unit = {
printf("This is a %s car. It is expensive.\n", carBand)
}
override def greeting(): Unit = {
println("Welcome to my BYD car!")
}
}
object TestCar {
def main(args: Array[String]): Unit = {
val car1 = new BMWcar
val car2 = new BYDcar
car1.greeting()
car1.info()
car2.greeting()
car2.info()
}
}
9 特质trait
// 特质1 CarId
trait CarId {
var id: Int
def currentId(): Int
}
// 特质2 CarGreeting
trait CarGreeting {
def greeting(msg: String) {println(msg)}
}
// 继承上面两个特质 用with
class BYDCarId extends CarId with CarGreeting {
var id = 10000
def currentId(): Int = {id += 1; id}
}
// 可以不用override 因为trait没有实现
class BMWCarId extends CarId with CarGreeting {
var id: Int = 20000
override def currentId(): Int = {
id += 1
id
}
}
object Test {
def main(args: Array[String]): Unit = {
val carId1 = new BYDCarId
val carId2 = new BMWCarId
carId1.greeting("Welcome to my first car!")
printf("My first CarId is %d.\n", carId1.currentId())
carId2.greeting("Welcome to my second car!")
printf("My second CarId is %d.\n", carId2.currentId())
}
}