0
votes

I have a Class named A that extends a Trait X. X has an abstract variable x that has been implemented in the class A. Class A uses one of the functions in Trait X named foo. I am trying to make a companion object of Class A and put in some 'static' method inside it named Ofoo. My problem is that Ofoo uses foo. So, I tried doing something like this:

trait X{
val x:String
def foo = {
    //Full implementation here
    }
}

case class A extends X{
val x = "barbaz"
// Class uses foo
}

object A extends X{
def Ofoo = {
    //This also needs to use foo
    }
}

I get an error saying the object A cannot be instantiated as the variable x is not defined in trait X. How should I structure A such that it can use the function foo defined in the trait X?

3
You should explain what you are really trying to accomplish (your real problem, not an abstraction of it). There is probably a simple solution, but it is hard to say if we don't really know what you are trying to do.toto2

3 Answers

3
votes

The compiler behaves as it should. There can be 2 things: Does foo use x?

If that is the case then it is required to have an Instance with x declared as the compiler says. You could say:

object A{
    def ofoo = new X{val x = "default"}.foo
}

If foo does not use x then I am not sure if it should even belong to the trait X. You could then create an object X and then have foo inside it something like:

trait X{
   val x:String
}

object X{
   def foo = {}
}
1
votes

How about implementing x in A? It's just an object; it has to obey the same rules, which include implementing the abstract members of any classes/traits that are being extended.

object A extends X {
  val x = "hello"
  ...
}

just because it's the companion object of a class A that already inherits from X and implements x, does not mean that object X somehow magically reuses it.

In fact, technically a class and it's companion object are not connected; their only relation exists by convention.


On the other hand, if you want to make sure the value of x is the same in both class A as well as object A, you can just define val x in object A and pull in that value in class A:

class A extends X {
  val x = X.x
  ...
}
object A extends X {
  val x = "shared-value-of-x"
  ...
}
0
votes

At any rate, x must be defined by object A or in one of its superclasses/supertraits.

Based of the previous proposals and the OP's responses, I'll assume that foo should not be accessible from elsewhere, thus:

package pack {

  trait X{
    val x:String
  }

  // Reachable only in the same source file
  sealed trait Y extends X{

   // if foo doesn't use x below, no need to extend X, though
   private[pack] def foo = {
      //Full implementation here
      println("x = "+x)
    }
  }

  case class A() extends X with Y{
    val x = "barbaz"
    // Class uses foo
    foo
  }

  object A extends X with Y{
    val x = "barbatruc" 
    def ofoo = {
      //This also needs to use foo
      foo
    }
  }

}

Actually I have a hard time to understand what the OP wants. I agree with toto2.