Scala开发教程(43): 组合和继承–小结

jerry Scala 2015年11月25日 收藏

前面我们基本完成了布局元素的函数库,现在我们就可以写个程序来使用这个函数库,下面显示螺旋线的程序如下:

object Spiral {
  val space = elem (" ")
  val corner = elem ("+")
  def spiral(nEdges:Int, direction:Int): Element = {
    if(nEdges==1)
      elem("+")
    else{
      val sp=spiral(nEdges -1, (direction +3) % 4)
      def verticalBar = elem ('|',1, sp.height)
      def horizontalBar = elem('-',sp.width,1)
      if(direction==0)
        (corner beside horizontalBar) above (sp beside space)
      else if (direction ==1)
        (sp above space) beside ( corner above verticalBar)
      else if(direction ==2 )
        (space beside sp) above (horizontalBar beside corner)
      else
        (verticalBar above corner) beside (space above sp)
  }
}
 
 def main(args:Array[String]) {
   val nSides=args(0).toInt
   println(spiral(nSides,0))
 }
}

因为Sprial为一单例对象,并包含main方法,因此它为一Scala应用程序,可以在命令行使用scala Sprial xx来运行这个应用。

root@mail:~/scala# scala Spiral 5
+----
|    
| ++ 
|  | 
+--+ 

root@mail:~/scala# scala Spiral 23
+----------------------
|                      
| +------------------+ 
| |                  | 
| | +--------------+ | 
| | |              | | 
| | | +----------+ | | 
| | | |          | | | 
| | | | +------+ | | | 
| | | | |      | | | | 
| | | | | +--+ | | | | 
| | | | | |  | | | | | 
| | | | | ++ | | | | | 
| | | | |    | | | | | 
| | | | +----+ | | | | 
| | | |        | | | | 
| | | +--------+ | | | 
| | |            | | | 
| | +------------+ | | 
| |                | | 
| +----------------+ | 
|                    | 
+--------------------+ 

这个例子的完整代码如下:

object Element {
  private class ArrayElement(val contents: Array[String])
    extends Element

  private class LineElement(s:String) extends Element {
    val contents=Array(s)
    override def width = s.length
    override def height = 1
  }

  private class UniformElement (ch :Char,
    override val width:Int,
    override val height:Int
  ) extends Element{
    private val line=ch.toString * width
    def contents = Array.fill(height)(line)
  }

  def elem(contents: Array[String]):Element =
   new ArrayElement(contents)

  def elem(chr:Char, width:Int, height:Int) :Element =
    new UniformElement(chr,width,height)

  def elem(line:String) :Element =
    new LineElement(line)
  }

import Element.elem

abstract class Element {
  def contents: Array[String]
  def height: Int = contents.length
  def width: Int =  contents(0).length
  def above(that: Element) :Element = {
    val this1=this widen that.width
    val that1=that widen this.width
    elem (this1.contents ++ that1.contents)
  }


  def beside(that: Element) :Element = {
    val this1=this heighten that.height
    val that1=that heighten this.height
    Element.elem(
      for(
        (line1,line2) <- this1.contents zip that1.contents
      ) yield line1+line2
    )
  }

  def widen(w: Int): Element =
  if (w <= width) this
  else {
    val left = Element.elem(' ', (w - width) / 2, height)
        var right = Element.elem(' ', w - width - left.width, height)
        left beside this beside right
  }

def heighten(h: Int): Element =
  if (h <= height) this
  else {
    val top = Element.elem(' ', width, (h - height) / 2)
        var bot = Element.elem(' ', width, h - height - top.height)
        top above this above bot
  }
  override def toString = contents mkString "\n"

}

object Spiral {
  val space = elem (" ")
  val corner = elem ("+")
  def spiral(nEdges:Int, direction:Int): Element = {
    if(nEdges==1)
      elem("+")
    else{
      val sp=spiral(nEdges -1, (direction +3) % 4)
      def verticalBar = elem ('|',1, sp.height)
      def horizontalBar = elem('-',sp.width,1)
      if(direction==0)
        (corner beside horizontalBar) above (sp beside space)
      else if (direction ==1)
        (sp above space) beside ( corner above verticalBar)
      else if(direction ==2 )
        (space beside sp) above (horizontalBar beside corner)
      else
        (verticalBar above corner) beside (space above sp)
  }
}

 def main(args:Array[String]) {
   val nSides=args(0).toInt
   println(spiral(nSides,0))
 }
}

到目前为止,你看到了Scala里与面向对象编程有关的更多的概念。其中,你遇到了抽象类,继承和派生,类层次,参数化字段,及方法重载。你应当已经建立了在Scala里构造不太小的类层次的感觉。