Search code examples
scalaabstract-classfactoryabstractcompanion-object

Calling methods from each other when using Abstact Class and Factory in Scala (Companion Object)


I'm following "Programming in Scala", on Chapter 10 Type Hierarchy (http://www.artima.com/pins1ed/composition-and-inheritance.html).

I'm receiving the following error in my Scala interactive shell:

scala> :load Element.scala
Loading Element.scala...
<console>:11: error: not found: type Element
                   ) extends Element
                             ^
<console>:13: error: not found: type Element
           private class LineElement(s: String) extends Element {
                                                        ^
<console>:23: error: not found: type Element
                   ) extends Element {
                             ^
<console>:28: error: not found: type Element
           def elem(contents:  Array[String]): Element = new ArrayElement(contents)
                                               ^
<console>:30: error: not found: type Element
           def elem(chr: Char, width: Int, height: Int): Element = new UniformElement(chr, width, height)
                                                         ^
<console>:32: error: not found: type Element
           def elem(line: String): Element = new LineElement(line)
                                   ^
<console>:7: error: not found: value Element
       import Element.elem
              ^
<console>:16: error: not found: value elem
               elem(this1.contents ++ that1.contents)
               ^
<console>:22: error: not found: value elem
               elem(
               ^
<console>:30: error: not found: value elem
                  val left = elem(' ', (w - width) / 2, height)
                             ^
<console>:31: error: not found: value elem
                  var right = elem(' ', w - width - left.width, height)
                              ^
<console>:38: error: not found: value elem
                   val top = elem(' ', width, (h - height) / 2)
                             ^
<console>:39: error: not found: value elem
                   var bot = elem(' ', width, h - height - top.height)
                             ^

Does anyone have any idea why 1) My object cannot recognize the companion class ("extends Element") 2) The method is unable to call another method within the same class/companion object?

I have my class set up as follows:

  1 object Element {
  2 
  3     private class ArrayElement(
  4             val contents: Array[String]
  5             ) extends Element
  6 
  7     private class LineElement(s: String) extends Element {
  8         val contents = Array(s)
  9             override def width = s.length
 10             override def height = 1
 11     }
 12 
 13     private class UniformElement(
 14             ch: Char,
 15             override val width: Int,
 16             override val height: Int
 17             ) extends Element {
 18         private val line = ch.toString * width
 19             def contents = Array.fill(height)(line)
 20     }
 21 
 22     def elem(contents:  Array[String]): Element = new ArrayElement(contents)
 23 
 24     def elem(chr: Char, width: Int, height: Int): Element = new UniformElement(chr, width, height)
 25 
 26     def elem(line: String): Element = new LineElement(line)
 27 }
 28
 29 import Element.elem
 30 abstract class Element {
 31     def contents:  Array[String]
 32 
 33     def width: Int = contents(0).length
 34     def height: Int = contents.length
 35 
 36     def above(that: Element): Element = {
 37         val this1 = this widen that.width
 38         val that1 = that widen this.width
 39         elem(this1.contents ++ that1.contents)
 40     }
 41 
 42     def beside(that: Element): Element = {
 43         val this1 = this heighten that.height
 44         val that1 = that heighten this.height
 45         elem(
 46         for ((line1, line2) <- this1.contents zip that1.contents)
 47         yield line1 + line2)
 48     }
 49 
 50     def widen(w: Int): Element =
 51        if (w <= width) this
 52        else {
 53            val left = elem(' ', (w - width) / 2, height)
 54            var right = elem(' ', w - width - left.width, height)
 55            left beside this beside right
 56        }
 57 
 58     def heighten(h: Int): Element =
 59         if (h <= height) this
 60         else {
 61             val top = elem(' ', width, (h - height) / 2)
 62             var bot = elem(' ', width, h - height - top.height)
 63             top above this above bot
 64         }
 65 
 66     override def toString = contents mkString "\n"
 67 }

Thanks for your help!


Update: I tried :paste instead of :load, and still get the following error message:

scala> :paste Element.scala
Pasting file Element.scala...
<console>:44: error: not found: value elem
               elem(this1.contents ++ that1.contents)
               ^
<console>:50: error: not found: value elem
               elem(
               ^
<console>:58: error: not found: value elem
                  val left = elem(' ', (w - width) / 2, height)
                             ^
<console>:59: error: not found: value elem
                  var right = elem(' ', w - width - left.width, height)
                              ^
<console>:66: error: not found: value elem
                   val top = elem(' ', width, (h - height) / 2)
                             ^
<console>:67: error: not found: value elem
                   var bot = elem(' ', width, h - height - top.height)
                             ^

Solution

  • looking through :help

    scala> :help
    ...
    :load <path>             interpret lines in a file
    :paste [-raw] [path]     enter paste mode or paste a file
    

    :load seems to be just an interpreter. Try :paste

    scala> :paste Element.scala
    Pasting file Element.scala...
    defined class Element
    defined object Element