Scala开发教程(40): 组合和继承–实现类Element的above,beside和toString()方法

jerry Scala 2015年11月25日 收藏

我们接着实现类Element的其它方法,如above, beside和toString方法。
above方法,意味着把一个布局元素放在另外一个布局元素的上方,也就是把这两个元素的contents的内容连接起来。我们首先实现above函数的第一个版本:

def above(that: Element) :Element =
    new ArrayElement(this.contents ++ that.contents)

Scala中Array 使用Java Array来实现,但添加很多其它方法,尤其是Scala中Array可以转换为scala.Seq类的实例对象,scala.Seq为一个序列结构并提供了许多方法来访问和转换这个序列。
实际上上面above的实现不是十分有效,因为它不允许你把不同长度的布局元素叠加到另外一个布局元素上面,但就目前来说,我们还是暂时使用这个实现,只使用同样长度的布局元素,后面再提供这个版本的增强版本。
下面我们再实现类Element的另外一个beside方法,把两个布局元素并排放置,和前面一样,为简单起见,我们暂时只考虑相同高度的两个布局元素:

def beside(that: Element) :Element = {
    val contents = new Array[String](this.contents.length)
    for(i <- 0 until this.contents.length)
      contents(i)=this.contents(i) + that.contents(i)
    new ArrayElement(contents)
  }

尽管上面的实现满足beside要求,但采用的还是指令式编程,我们使用函数说编程可以实现下面简化代码:

def beside(that: Element) :Element = {
    new ArrayElement(
      for(
        (line1,line2) <- this.contents zip that.contents
      ) yield line1+line2
    )
  } 

这里我们使用了Array的zip 操作符,可以用来将两个数组转换成二元组的数组,zip 分别取两个数组对应的元素组成一个新的二元祖,比如:

scala> Array( 1,2,3) zip Array("a","b")
res0: Array[(Int, String)] = Array((1,a), (2,b))

如果一个数组长度大于另外一个数组,多余的元素被忽略。 for 的yield部分用来构成一个新元素。

最后我们实现Element的toString方法用来显示布局元素的内容:

override def toString = contents mkString "\n"

这里使用mkString函数,这个函数可以应用到任何序列数据结构(包括数组),也就是把contents的每个元素调用toString,然后使用?\n?分隔。