Case class extending trait not working with copy - scala

I try
trait Foo[A] {
def copy(int: Int): A
}
case class Bar(int: Int) extends Foo[Bar]
but I get
error: class Bar needs to be abstract, since method copy in trait Foo of type (int: Int)this.Bar is not defined
Since Bar is a case class, it automatically defines a copy method with exactly this signature.
Why doesn't the Foo class satisfy the interface defined by the trait Bar?

I am quoting the Scala's specification:
A method named copy is implicitly added to every case class unless the class already has a member (directly defined or inherited) with that name, or the class has a repeated parameter.

Related

Scala Type Tags - Fully qualified versus non-fully qualified

I have some code (difficult to share and I've not been able to trivially replicate) which is throwing the following error:
found: reflect.runtime.universe.TypeTag[com.company.some.package.Individ]
required: reflect.runtime.universe.TypeTag[Individ]
My code was unable to find a TypeTag, so I attempted to pass it explicitly. I.e. Instead of
abstract class Validator[T<: Product: TypeTag] {...}
class Validator[Individ] extends Validator[Individ] {...} // Implicits not found
I tried..
abstract class Validator[T<: Product](implicit tt: TypeTag[T]) {...}
implicit val tt = typeTag[Individ]
class Validator[Individ] extends Validator[Individ]()(tt) {...} // Wrong type, as above
Individ is just a case class
Any ideas?
What you probably want is
class IndividValidator extends Validator[Individ] {...}
When you write
class IndividValidator[Individ] extends Validator[Individ]()(tt)
you create a new generic class IndividValidator with a generic type parameter called Individ and it shadows your imported class. So the term Individ in the extends Validator[Individ] is matched to this type parameter rather than your com.company.some.package.Individ. To put it otherwise, this is the same code as
class IndividValidator[A] extends Validator[A]()(tt)
which is clearly not what you want.

Is it possible to mix in trait in abstract class but make it specific to each subclass in Scala?

I wrote some code for Logic Expressions in Scala and I was wondering if I could find a way to mix in a trait into an abstract class, so I don't have to extend it in every subclass. Here is what I've got:
abstract class LogicExpression
case class Literal(lit:String, not:Boolean) extends LogicExpression with Ordered[Literal]
case class Conjunction(lits:Seq[Literal]) extends LogicExpression with Ordered[Conjunction]
...
I want every case class to be only Comparable to another instance of itself (Literal with Literal, Conjunction only with Conjunction, etc) but I would like to extend the trait in the abstract class so I don't have to repeat it on every subclass. Is this possible?
I tried
abstract class LogicExpression extends Ordered[LogicFormula]
but that would also allow comparing Literal with Conjunction for example.
You need something like this:
sealed trait LogicExpression[T <: LogicExpression[T]] extends Ordered[T]
case class SomeExpression() extends LogicExpression[SomeExpression] {
override def compare(that: SomeExpression) = ???
}

Passing type information in scala

If I have some class heirarchy defined like this
sealed trait A
case class B() extends A
case class C() extends A
// and so on ..
and in a different location I want to call some method dynamically passing above classes as type to that function
(eg: method[B](..){..} or method[C](..){..})
How can this be achieved at runtime?

Return class instance using generic inside companion object for method specified in trait

In Scala I want to return a instance of a class for a method defined in a trait which uses generics, the code example I have is this:
File 1
package packOne
import packTwo.A
trait MyTrait[T <: MyTrait[T <: A]] {
def otherFunct(): String
def funct[T <: A](): T
}
File 2
package packTwo
import packOne.MyTrait
abstract class A(someParameter: String) {}
class B(someParameter: String) extends A(someParameter) {}
object B extends MyTrait[B] { // <--- the B inside MyTrait here is the class not the object, or at least that is what I want
def otherFunct(): String = "Hello"
def funct[B](): C = new B("hi") // <--- I think here is the key
}
basically what I want is an interface that have method to return a concrete implementation of class A, in an implementing object (which happen to be a companion object for a class extending A).
Why do I want that to be on an object?, is because I want to call that method without the need of an instance (like an static method in java), so that I can call B.funct() and have an instance of B class kind of like a factory method, for other classes extending A for example a call to X.funct will return an instance of class X.
I have tried to remove the generic type from the function definition except on the return type of the function and just leave it in the trait definition (like def funct(): T) but that does not work either.
I am quite new to Scala so if you could explain it for dummies and avoid complex scala unique concepts I would appreciate
How about simply:
trait A
class B(someParameter: String) extends A
trait MyTrait[T <: A] {
def otherFunct: String //Parentheses on parameterless methods with no side effects and no serious computation are generally unidiomatic in Scala
def funct: T //Note, no generic parameter on this method
}
object B extends MyTrait[B] {
def otherFunct = "Hello"
def funct = new B("hi")
}
And then:
B.funct //returns a new `B`
The apply method is often used in this factory style (e.g. Seq.apply() which is equivalent to Seq())

Scala: Get companion class in companion object

I need to define a val in my companion object which is initialized with a method which takes the companion class as parameter.
I want to handle this with traits to not repeat myself. My Problem ist, that X.getClass ist not the same as classOf[X]. The first is the class of the companion object and the second is the class of the companion class, but I need to get the companion class without hardcoding it directly.
Basically I need something like this:
trait Foo {
}
object FooCompanionObject[f <: Foo] {
val fClazz = classOf[f]
}
// Bar's fClass should be classOf[Bar]
case class Bar extends Foo;
object Bar extends FooCompanionObject[Bar];
The problem is that I cannot get the class of an generic type due to type erasure
There are several problems in your code. First, as you already said, the type will be erased, second objects (object FooCompanionObject[f <: Foo]) don't take type parameters and third, objects can not be extended (object Bar extends FooCompanionObject). To do what you want, you have to create an abstract base class for your companion objects, that takes a type parameter, which may be constrained to a specific type if you like, and has to be context bound on ClassTag. From the ClassTag you can then get the runtime class by calling runtimeClass on it. The final solution could look like this:
import scala.reflect.ClassTag
import scala.reflect.classTag
trait Foo
abstract class Companion[A <: Foo : ClassTag] {
val fClazz = classTag[A].runtimeClass
}
class Bar extends Foo
object Bar extends Companion[Bar]
scala> Bar.fClazz
res2: Class[_] = class Bar