Scala subtype parameter - scala

I created a class Project extending a Model:
abstract class Model
case class Project(...) extends Model
and an object Table extending Base:
abstract class Base {
val tableForm: Form[Model]
}
object Table extends Base {
val tableForm: Form[Project] = (...)
}
Why is it that it won't compile and how can I fix it? ("overriding method/value tableForm in class Base of type => Form[Model]")
I just wanted to force all subclasses of Base to have a tableForm attribute.

Because Form[Project] is not a subclass of Form[Model]. So the compiler complains about incompatible type in overriding value.
Form[T] is invariant. You can read the variance doc
To fix this, you can add a type parameter to Base.
abstract class Base[M <: Model] {
val tableForm: Test[M]
}
object Table extends Base[Project] {
val tableForm: Test[Project] = ???
}

Related

In scala, why type alias in a class cannot be referred for inheritance?

I have the following classes defined:
file: PyRef.scala:
package mypackage
class PyBinding() {
...
}
trait PyRef {
type Binding = PyBinding
}
file: Link.scala:
class Link() extends PyRef {
override type Binding = Link.PyBindingImpl
}
object Link {
class PyBindingImpl() extends PyRef#Binding() {
}
}
In compilation, the following error was thrown:
Error:(222, 34) class type required but mypackage.PyBinding found
) extends PyRef#Binding() {
Why this happens and what should I do to circumvent it? I'm using Scala 2.10.
I don't think you can use type projections A#B in Scala as instantiatable class types. The following two things work
trait Link {
class PyBindingImpl() extends PyBinding()
}
trait Link {
val ref: PyRef
class PyBindingImpl() extends ref.Binding()
}

WIth Squeryl (using Lift), how can I make two model classes a subclass of the same class?

Using Lift with Squeryl, how can I make two classes a subclass of the same class?
My classes look like the following:
class SubClass1 extends Record[SubClass1] with KeyedRecord[SubClass1] with CreatedUpdated[SubClass1] {
val id = ...
val field1a = StringField(...)
...
}
class SubClass2 extends Record[SubClass2] with KeyedRecord[SubClass2] with CreatedUpdated[SubClass2] {
val id = ...
val field2a = StringField(...)
}
I want SubClass1 and SubClass2 each to be a child class of some other class, say MyParentClass. So I would think that I would have to do something like this:
abstract class MyParentClass extends Record[MyParentClass] with KeyedRecord[MyParentClass] with CreatedUpdated[MyParentClass] {}
and then
class SubClass1 extends MyParentClass {
val id = ...
val field1a = StringField(...)
...
}
class SubClass2 extends MyParentClass {
val id = ...
val field2a = StringField(...)
...
}
This gives me errors, such as the fields (StringField) etc. not conforming to the right type. Any suggestions on how to do this?
Thanks,
You abstract superclass can't define a concrete type parameter, since it needs to be overriden by the subclasses. Try:
abstract class MyParentClass[A <: MyParentClass]
extends Record[A] with KeyedRecord[A] with CreatedUpdated[A]
Then:
class SubClass extends MyParentClass[SubClass]

Reify name of class implementing trait as String, from the trait itself

I have a trait that's implemented by a large number of classes, and I'd like to use the names of the classes that implement this trait at runtime, but with as much code centralized as possible.
Specifically, in my code, I'm using tokens to represent classes to be initialized at runtime. The tokens carry configuration, and the actual class is instantiated as needed via the token, combined with run-time information. For linking with resources outside of my app, I want to be able to access the name of the class for which a token is defined. See the example:
trait Token[Cls] {
val className = ???
// Example generic method depending on final class name
def printClassName = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
So, I'm trying to implement className. Ideally, I can pull this information once at compile time. How can I do this, while keeping boilerplate code out of ClassA? Although, if I can drop the type parameter and get the name of the class implementing the Token trait at runtime, that's great too.
Due to Type Erasure Cls is not available on runtime anymore. To get the informations at runtime, you need to use a TypeTag (in your case a ClassTag).
Your code could look like this:
import scala.reflect._
trait Token[Cls] {
def className(implicit ct: ClassTag[Cls]) = ct.runtimeClass.getName
// Example generic method depending on final class name
def printClassName(implicit ct: ClassTag[Cls]) = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
or if it is possible for you to let Token be an class, you could use the ClassTag context bounds:
import scala.reflect._
class Token[Cls: ClassTag] {
def className = classTag[Cls].runtimeClass.getName
// Example generic method depending on final class name
def printClassName = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
For more informations on TypeTags/ClassTags see Scala: What is a TypeTag and how do I use it?

base class constructor parameter in trait

I have a base class with some constructor parameter:
abstract class HugeClass(implicit context: ContextClass) {
...
}
Because the class gets bigger and bigger and only some subclasses need some special behaviour, I want to refactor it into a trait. However, I still need access to context in the trait. I tried this:
trait SomeTrait extends HugeClass {
def myMethod = {
context.method
}
}
But the scala compiler says: not found: value context. How can I solve that?
Parameter context is turned into a private field. The fact that a parameter or a member is implicit does not mean it is public - it is implicit only within the class it is visible in (HugeClass).
Turn context into a val:
abstract class HugeClass(implicit val context: ContextClass) {
...
}
and it will work.

Seamless weaving of trait

I would like to automatically weave the definition of a new function say introduced by an extending trait Ext into an abstract class A:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait A extends super.A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B
b.say
}
However, I obtain the following error:
<console>:12: error: value say is not a member of Test.B
b.say
Any way of doing it?
It seems you are trying to use virtual classes, which is a feature not available in Scala.
Once A and B are defined they can't be redefined (like method overriding).
abstract class A
class B extends A
On the other hand, given your example, your objective could be achieved by a simple mixin. Here it is with few rewrites:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait CanSay extends A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B with CanSay
def apply = b.say
}
Test.apply
No sure it will really help, but at least will help you understand what is going on.
Okay, as I said in a comment, it's not entirely clear what you're trying to do here, so I can't really try to suggest ways to do it. However, the approach you're using at the moment will not work.
Consider the class Hierarchy in this situation. At the base, we have A, which is then subclassed with B (in Base) and with Ext.A. These are not related save by their shared supertype, so you'll never find a say method on an instance of B.
The confusion possibly arises through the use of the word abstract. An abstract modifier on a class (even an inner class) does not make it an abstract member of the parent class, but denotes that it itself may have abstract members. There are ways of giving a class an abstract class member - through type parameters or type members. Unfortunately, you cannot derive from these AFAIK.