How do I pass an inherited variable into a Auxiliary constructor from a trait

Viewed 88

I'm looking to get the value bork and pass it to a class into the class in the constuctor.

trait dog {
  lazy val bork = "bork"
}


class Animal(val firstName: String, dogCommand: DogCommand) extends dog{
  def this(firstName: String) {
    this(firstName, DogCommand(bork))
  }
  
  def getDogCommand(): Unit = {
    dogCommand.getCommand()
  }
}

case class DogCommand(command: String) {
  def getCommand() :Unit = {
      println(command)
  }
}

val myDog = new Animal("first")

myDog.getDogCommand()

I usually get - error: not found: value bork

2 Answers

The problem is that bork is a value on dog but there is no instance of dog available to read the bork from. this is a constructor so it doesn't have access to the value that is being constructed.

This is one solution that retains most of the original code:

trait dog {
  def bork = dog.DefaultBork
}

object dog {
  val DefaultBork = "bork"
}

class Animal(val firstName: String, dogCommand: DogCommand) extends dog {
  def this(firstName: String) = this(firstName, DogCommand(dog.DefaultBork))

  ...
}

You could consider removing the default value of bork in dog so that any class implementing the trait is required to provide a value for bork. (It can always use DefaultBork if it wants to retain the default value)

For one item, your this constructor is incorrect. I also renamed Dog. As for your lazy val that wouldn't work on a trait. See more here why scala don't allow define lazy val in trait?. Even if you make it non-lazy, that value is not initialized yet until construction when that val is not available, yet. Another problem would also be logic, an Animal is not Dog, but the other way around. Here is an alternative: https://scastie.scala-lang.org/WnhxzSn6QtOf5vo1epDDqQ Hope that helps. ;)

trait Dog {
  lazy val bork = "bork"
}


class Animal(val firstName: String, dogCommand: DogCommand) extends Dog {
  def this(firstName: String) = this(firstName, DogCommand(bork))
  
  def getDogCommand(): Unit = {
    dogCommand.getCommand()
  }
}

case class DogCommand(command: String) {
  def getCommand() :Unit = {
      println(command)
  }
}

val myDog = new Animal("first")

myDog.getDogCommand()
Related