1. scala Classes类
scala中的类有以下几种元素(和java中的类有点类似):
类(class),属性(field),方法(method)
来个简单的例子
class Animal {
val name: String = "jack"
var age: Int = 1
def eat: Unit = println("eat...")
override def toString: String = s"[name=$name, age=$age]"
}
object Main {
def main(args: Array[String]): Unit = {
val animal = new Animal
println(animal.name + "::" + animal.age)
println(animal)
animal.eat
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
在上面的例子中 定义了一个Animal类,其中有两个属性 , 分别是val(相当于java中的final)类型的name 和var(普通变量)类型的age。还定义一个eat方法
当方法体内只有一行代码时,可以省略大括号{}, 重写了toString方法 scala中所有的类都有一个顶层父类scala.Any和java中的java.lang.Object类似。下面贴一下Any的源码
abstract class Any {
def equals(that: Any): Boolean
def hashCode(): Int
def toString(): String
final def getClass(): Class[_] = sys.error("getClass")
final def ==(that: Any): Boolean = this equals that
final def != (that: Any): Boolean = !(this == that)
final def ##(): Int = sys.error("##")
final def isInstanceOf[T0]: Boolean = sys.error("isInstanceOf")
final def asInstanceOf[T0]: T0 = sys.error("asInstanceOf")
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
scala中的类可以带上类参数使得代码更简洁 可以改写一下Animal的代码
class Animal(nameParam: String, ageParam: Int) {
val name: String = nameParam
var age: Int = ageParam
def eat: Unit = println("eat...")
override def toString: String = s"[name=$name, age=$age]"
}
object Main {
def main(args: Array[String]): Unit = {
val animal = new Animal("jack", 2)
println(animal.name + "::" + animal.age)
println(animal)
animal.eat
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
当然类参数还可以有默认值 就是当不传该参数的时候使用默认值 如下
class Animal(nameParam: String = "jack", ageParam: Int) {
val name: String = nameParam
var age: Int = ageParam
def eat: Unit = println("eat...")
override def toString: String = s"[name=$name, age=$age]"
}
object Main {
def main(args: Array[String]): Unit = {
val animal = new Animal(ageParam = 2)
println(animal.name + "::" + animal.age)
println(animal)
animal.eat
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
scala中还有一种单例对象,上面的object Main就是一个单例对象, scala中类还可以有一个伴生单例对象 而且它们彼此之间都可以相互访问自己的属性或方法 尽管可能是private的[说明: scala中没加修饰符的属性或方法都是public的], scala中的属性或方法都没有static类型的,要想定义此类型可在伴生对象中定义。如下代码所示:
class Animal(nameParam: String = "jack", ageParam: Int) {
val name: String = nameParam
var age: Int = ageParam
def eat: Unit = println("eat...")
override def toString: String = Animal.show(this)
}
object Animal {
val color: String = "black"
def sleep: Unit = println("sleep")
def show(animal: Animal): String = s"[name=${animal.name}, age=${animal.age}]"
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
上面的object Animal就是类Animal伴生的单例对象,其中定义的属性和方法都是static的
2. scala 修饰符(modifiers)
scala中的修饰有private, protected两种,未加修饰符的就是public范围的。
1,private只能在本类中访问和java中private差不多,但是不同的是scala中的外部类不能访问内部类的private修饰的属性或方法, 但是也有手段来实现想java中的private的效果。来看代码
class Outer {
private val nameOuter = "outer"
class Inner {
private val nameInner = "inner"
}
def inner(inner: Inner): String = inner.nameInner
}
使用private[Outer]指定修饰符范围:就是在Outer这个类的范围内就可以访问, 看代码:
class Outer {
private val nameOuter = "outer"
class Inner {
private[Outer] val nameInner = "inner"
}
def inner(inner: Inner): String = inner.nameInner
}
2, protected 修饰符
先来对比下scala和java中protected的范围
java中 protected修饰范围: 所有的子类和在同一包下的类
scala中 protected修饰范围: 所有子类
看来还是不同的 但是在scala中还是可以实现在java中的效果。
package pkg1 {
class Super {
protected val name = "super"
}
class Other {
def show(su: Super): String = su.name
}
}
package pkg2 {
import pkg1._
class Sub extends Super {
def show(su: Super): String = su.name
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
scala中不仅可以向java那样package在文件的头部, 也可以像上面的代码一样定义package
比如
package pkg1
package pkg2{
}
import pkg1._ scala中import可以在任何地方出现 _下划线相当于java中的*
好了 再次回到protected修饰符的问题上 如何在scala中实现protected在java中的效果,看代码
package pkg1 {
class Super {
protected[pkg1] val name = "super"
}
class Other {
def show(su: Super): String = su.name
}
}
package pkg2 {
import scala.date20170506.pkg1._
class Sub extends Super {
def show(su: Super): String = su.name
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
现在来详细看看scala中的修饰符的范围定义问题 只能说非常灵活
private[X] val f = "f" X可以还是包名 类名 单例Object名 还可以是this
包对象 package object 所有包内类 对象均可以访问该对象定义的属性和方法
package object pkg1 {
val name = "pkg1"
def show: Unit = name
}