从零开始学Scala系列(六)之类(Classes)和对象(Objects)

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)
    //val animal = new Animal(ageParam = 2, nameParam = "jack") 还可以指定参数名称赋值 很灵活
    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)
    //val animal = new Animal("rose", 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"
  }
  //这里是无法编译通过的 报错 
  //Error:(27, 43) value nameInner in class Inner cannot be accessed in Outer.this.Inner
  def inner(inner: Inner): String = inner.nameInner  
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

使用private[Outer]指定修饰符范围:就是在Outer这个类的范围内就可以访问, 看代码:

class Outer {
  private val nameOuter = "outer"
  class Inner {
    private[Outer] val nameInner = "inner"
  }
  //达到了和java中一样的效果  很灵活
  def inner(inner: Inner): String = inner.nameInner
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2, protected 修饰符 
先来对比下scala和java中protected的范围

java中 protected修饰范围: 所有的子类和在同一包下的类 
scala中 protected修饰范围: 所有子类 
看来还是不同的 但是在scala中还是可以实现在java中的效果。

package pkg1 {
  class Super {
    protected val name = "super"
  }
  class Other {
    //这里是编译不能通过的 因为Other不是Super的子类
    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{
//这里代码都是定义在pkg1.pkg2包里的 都是可以叠加的
}

import pkg1._ scala中import可以在任何地方出现 _下划线相当于java中的*
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

好了 再次回到protected修饰符的问题上 如何在scala中实现protected在java中的效果,看代码

package pkg1 {
  class Super {
    //可以在包pkg1任何范围内访问
    protected[pkg1] val name = "super"
  }
  class Other {
    //这里是编译不能通过的 因为Other不是Super的子类
    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
   
   
  • 1

包对象 package object 所有包内类 对象均可以访问该对象定义的属性和方法

package object pkg1 {
  val name = "pkg1"
  def show: Unit = name
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值