Scala:类,对象和特征(接口)

来源:互联网 发布:c语言进阶书籍 编辑:程序博客网 时间:2024/03/28 21:57

http://blog.csdn.net/pipisorry/article/details/52902609

Scala类和对象

类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。

类的创建和实例化

class Point(xc: Int, yc: Int) {   var x: Int = xc   var y: Int = yc   def move(dx: Int, dy: Int) {      x = x + dx      y = y + dy      println ("x 的坐标点: " + x);      println ("y 的坐标点: " + y);   }}

Scala中的类不声明为public,一个Scala源文件中可以有多个类。

以上实例的类定义了两个变量 xy ,一个方法:move,方法没有返回值。

Scala 的类定义可以有参数,称为类参数,如上面的 xc, yc,类参数在整个类中都可以访问。

接着我们可以使用 new 来实例化类,并访问类中的方法和变量:

import java.io._class Point(xc: Int, yc: Int) {   var x: Int = xc   var y: Int = yc   def move(dx: Int, dy: Int) {      x = x + dx      y = y + dy      println ("x 的坐标点: " + x);      println ("y 的坐标点: " + y);   }}object Test {   def main(args: Array[String]) {      val pt = new Point(10, 20);      // 移到一个新的位置      pt.move(10, 10);   }}

实例的默认参数

def this() = this(x = 1, y = 2)

Scala 继承

Scala继承一个基类跟Java很相似, 但我们需要注意一下几点:

  • 1、重写一个非抽象方法必须使用override修饰符。
  • 2、只有主构造函数才可以往基类的构造函数里写参数。
  • 3、在子类中重写超类的抽象方法时,你不需要使用override关键字。

继承会继承父类的所有属性和方法,Scala 只允许继承一个父类。

Scala重写一个非抽象方法,必须用override修饰符。

实例:

class Point(xc: Int, yc: Int) {   var x: Int = xc   var y: Int = yc   def move(dx: Int, dy: Int) {      x = x + dx      y = y + dy      println ("x 的坐标点: " + x);      println ("y 的坐标点: " + y);   }}class Location(override val xc: Int, override val yc: Int,   val zc :Int) extends Point(xc, yc){   var z: Int = zc   def move(dx: Int, dy: Int, dz: Int) {      x = x + dx      y = y + dy      z = z + dz      println ("x 的坐标点 : " + x);      println ("y 的坐标点 : " + y);      println ("z 的坐标点 : " + z);   }}

Scala 使用 extends 关键字来继承一个类。实例中 Location 类继承了 Point 类。Point 称为父类(基类),Location 称为子类。

override val xc 为重写了父类的字段。

皮皮blog


Scala单例对象与伴生对象

Scala的单例对象

Scala没有 static 这个东西,不能定义静态成员,而是代之定义单例对象(singleton object)。以object关键字定义。
对象定义了某个类的单个实例,包含了你想要的特性:

object Accounts{    private var lastNumber = 0    def newUniqueNumber() = { lastNumber += 1; lastNumber}}

当你在应用程序中需要一个新的唯一账号时,调用Account.newUniqueNumber()即可。
对象的构造器在该对象第一次被使用时调用。

在下面几个场景下可以使用Scala单例对象:

- 作为存放工具函数或常量的地方- 高效地共享单个不可变实例- 需要使用单个实例来协调某个服务时

类和单例对象间的差别是,单例对象不带参数,而类可以。因为单例对象不是用new关键字实例化的,所以没机会传递给它实例化参数。每个单例对象都被实现为虚拟类(synthetic class)的实例,并指向静态的变量,因为它们与Java静态类有相同的初始化语义。

独立对象(standalone object)

不与伴生类共享名称的单例对象称为独立对象。它可以用在很多地方,例如作为相关功能方法的工具类,或者定义Scala应用的入口点。

伴生对象(companion object)

当单例对象与某个类共享同一个名称时,它就被称为是这个类的伴生对象(companion object)。类和它的伴生对象必须定义在同一个源文件中。类被称为是这个单例对象的伴生类(companion class)。类和它的伴生对象可以互相访问其私有成员

1
2
3
4
5
6
7
8
9
10
11
class Account {
val id = Account.newUniqueNumber()
private var balance = 0.0
def deposit(amount: Double){ balance += amount }
...
}
object Account { //伴生对象
private var lastNumber = 0
def newUniqueNumber() = { lastNumber += 1; lastNumber}
}

注意

  • 类的伴生对象可以被访问,但并不在作用域当中。Account类必须通过Account.newUniqueNumber()来调用伴生对象的方法。
  • 在REPL中,要同时定义类和对象,必须用粘贴模式。键入:paste,然后键入或粘贴类和对象的定义,最后一Ctrl+D退出粘贴模式。

将伴生对象作为工厂使用

我们通常将伴生对象作为工厂使用。
下面是一个简单的例子,可以不需要使用’new’来创建一个实例了。

1
2
3
4
5
class Bar(foo: String)
object Bar {
def apply(foo: String) = new Bar(foo)
}

单例对象实例

import java.io._class Point(val xc: Int, val yc: Int) {   var x: Int = xc   var y: Int = yc   def move(dx: Int, dy: Int) {      x = x + dx      y = y + dy   }}object Test {   def main(args: Array[String]) {      val point = new Point(10, 20)      printPoint      def printPoint{         println ("x 的坐标点 : " + point.x);         println ("y 的坐标点 : " + point.y);      }   }}

伴生对象实例

/* 文件名:Marker.scala */// 私有构造方法class Marker private(val color:String) {  println("创建" + this)  override def toString(): String = "颜色标记:"+ color}// 伴生对象,与类共享名字,可以访问类的私有属性和方法object Marker{    private val markers: Map[String, Marker] = Map(  //一调用这个函数,就会创建3个class Marker      "red" -> new Marker("red"),      "blue" -> new Marker("blue"),      "green" -> new Marker("green")    )    def apply(color:String) = {      if(markers.contains(color)) markers(color) else null    }    def getMarker(color:String) = {       if(markers.contains(color)) markers(color) else null    }    def main(args: Array[String]) {         println(Marker("red"))       //println会调用object Marker的toString函数,伴生对象就直接调用class Marker的toString函数了。        // 单例函数调用,省略了.(点)符号  println(Marker getMarker "blue")      }}
$ scalac Marker.scala $ scala Marker创建颜色标记:red创建颜色标记:blue创建颜色标记:green颜色标记:red颜色标记:blue

[【Scala】单例对象与伴生对象]

皮皮blog



Scala Trait(特征)

Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大。

与接口不同的是,它还可以定义属性和方法的实现。

一般情况下Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承。

Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait,如下所示:

trait Equal {  def isEqual(x: Any): Boolean  def isNotEqual(x: Any): Boolean = !isEqual(x)}

以上Trait(特征)由两个方法组成:isEqualisNotEqual。isEqual 方法没有定义方法的实现,isNotEqual定义了方法的实现。子类继承特征可以实现未被实现的方法。所以其实 Scala Trait(特征)更像 Java 的抽象类。

特征构造顺序

特征也可以有构造器,由字段的初始化和其他特征体中的语句构成。这些语句在任何混入该特征的对象在构造是都会被执行。

构造器的执行顺序:

  • 调用超类的构造器;
  • 特征构造器在超类构造器之后、类构造器之前执行;
  • 特质由左到右被构造;
  • 每个特征当中,父特质先被构造;
  • 如果多个特征共有一个父特质,父特质不会被重复构造
  • 所有特征被构造完毕,子类被构造。

构造器的顺序是类的线性化的反向。线性化是描述某个类型的所有超类型的一种技术规格。

from: http://blog.csdn.net/pipisorry/article/details/52902609

ref:


0 0
原创粉丝点击