Use scala reflection to initiate class with internal objects - scala

I have a class such as this:
class NormalClass[T <: NormalClass[T]] {
object One
object Two
}
and I wish to be able to create a new instance of the above class in a typed trait. The following def make in MetaClass creates an instance of T but it lacks the internal objects associated with NormalClass.
trait MetaClass[T <: NormalClass[T]] {
def make:T = this.getClass.getSuperclass.newInstance.asInstanceOf[T]
}
I have two questions, what is the reason for the missing objects and what is the best way, using reflection, to initiate a new class with internal objects from its type
EDIT: More Detail
The problem I am facing is if I then create an instance using make e.g. var f = make and I try to access and object method e.g. f.One.getSomething I get the error value One is not a member of type parameter T.

So I think your problem in particular is the reflection:
this.getClass.getSuperclass.newInstance.asInstanceOf[T]
Here, this is your instance of MetaClass, and there's no particular reason to believe that the superclass of this is the class you want to instantiate. For example:
class Foo extends NormalClass[Foo]
object Foo extends MetaClass[Foo]
In this case, the superclass of the object Foo is not a NormalClass at all, it's java.lang.Object. As a result, it won't have members like One or Two, and you'll get a ClassCastException if you try to cast it to T.
If you want the make method to instantiate an object of type T, then you need to get the runtime class of T, and then use that to create the new instance. You can accomplish this by implicitly acquiring a ClassTag:
class NormalClass[T <: NormalClass[T]] {
object One
object Two
}
trait MetaClass[T <: NormalClass[T]] {
def make(implicit classTag: scala.reflect.ClassTag[T]): T =
classTag.runtimeClass.newInstance.asInstanceOf[T]
}
// declare a class and an object for creating instances of that class
class Foo extends NormalClass[Foo]
object Foo extends MetaClass[Foo]
// create a new instance of Foo and access its fields
val foo = Foo.make
foo.One
foo.Two

I'm not sure what the issue is. This works for me:
scala> :paste
// Entering paste mode (ctrl-D to finish)
class NormalClass[T <: NormalClass[T]] {
object One
object Two
}
trait MetaClass[T <: NormalClass[T]] {
def make:T = this.getClass.getSuperclass.newInstance.asInstanceOf[T]
}
class X extends NormalClass[X]
// Exiting paste mode, now interpreting.
defined class NormalClass
defined trait MetaClass
defined class X
scala> new X with MetaClass[X]
res0: X with MetaClass[X] = $anon$1#404fe94c
scala> res0.One
res1: res0.One.type = NormalClass$One$#53d9f80
scala> res0.Two
res2: res0.Two.type = NormalClass$Two$#4d0948bd
If that doesn't answer your question, please clarify the issue you're having.

Related

Scala reflection to instantiate scala.slick.lifted.TableQuery

I have this base trait
trait MyBase {
type M
type T <: Table[M]
val query: TableQuery[T]
}
Where TableQuery is scala.slick.lifted.TableQuery
My subclasses instantiate TableQuery like so:
type M = Account
type T = AccountsTable
val query = TableQuery[T]
I'd like to instantiate the TableQuery in the base trait, possibly by using a lazy val, i.e.
lazy val query: TableQuery[T] = {
...
}
I've been playing around with reflection, but haven't had much luck.
If I understand correctly, what you want is to be able to extend
MyBase by simply defining M and T but without having to explicitly instantiate the TableQuery in each derived class.
Using reflection is not really an option because normally you use TableQuery.apply
for that (as in val query = TableQuery[MyTable]), and this is implemented through a macro,
so you've got a "runtime vs compile-time" issue.
If you absolutely need MyBase to be a trait (as opposed to a class), then I don't see any viable solution.
However if you can turn MyBase into a class and turn M and T into type parameters (instead of abstract types), then there is at least one solution.
As I hinted in another related question (How to define generic type in Scala?), you can
define a type class (say TableQueryBuilder) to capture the call to TableQuery.apply (at the point where the concrete type is known) along with an implicit macro (say TableQueryBuilder.builderForTable) to provide
an instance of this type class. You can then define a method (say TableQueryBuilder.build) to actually instantiate the TableQuery, which will just delegate to job to the type class.
// NOTE: tested with scala 2.11.0 & slick 3.0.0
import scala.reflect.macros.Context
import scala.language.experimental.macros
object TableQueryBuilderMacro {
def createBuilderImpl[T<:AbstractTable[_]:c.WeakTypeTag](c: Context) = {
import c.universe._
val T = weakTypeOf[T]
q"""new TableQueryBuilder[$T]{
def apply(): TableQuery[$T] = {
TableQuery[$T]
}
}"""
}
}
trait TableQueryBuilder[T<:AbstractTable[_]] {
def apply(): TableQuery[T]
}
object TableQueryBuilder {
implicit def builderForTable[T<:AbstractTable[_]]: TableQueryBuilder[T] = macro TableQueryBuilderMacro.createBuilderImpl[T]
def build[T<:AbstractTable[_]:TableQueryBuilder](): TableQuery[T] = implicitly[TableQueryBuilder[T]].apply()
}
The net effect is that you don't need anymore to know the concrete value of the type T in order to be able to instantiate a TableQuery[T],
provided that you have an implicit instance of TableQueryBuilder[T] in scope. In other words, you can shift the need to know the concrete value of T
up to the point where you actually know it.
MyBase (now a class) can then be implemented like this:
class MyBase[M, T <: Table[M] : TableQueryBuilder] {
lazy val query: TableQuery[T] = TableQueryBuilder.build[T]
}
And you can then extend it without the need to explcitly call TableQuery.apply:
class Coffees(tag: Tag) extends Table[(String, Double)](tag, "COFFEES") {
def name = column[String]("COF_NAME")
def price = column[Double]("PRICE")
def * = (name, price)
}
class Derived extends MyBase[(String, Double), Coffees] // That's it!
What happens here is that in Derived's constructor, an implicit value for TableQueryBuilder[Coffees] is implicitly
passed to MyBase's constructor.
The reason why you cannot apply this pattern if MyBase were a trait is pretty mundane: trait constructors cannot have parameters, let alone implicit parameters, so there would be no implicit way
to pass the TableQueryBuilder instance.

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: how to define an object with explicit class type

I understand the difference between object and class. Object is a singleton with anonymous class type. But in my play framework within xxx.scala.html file, it doesn't recorgnize the object name as type name. It report error that no type found. For instance:
Object ABC extends Enumeration{
....
}
In xxx.scala.html, define a variable abc:ABC, it will report no type found error, while other class type can be easily defined in this file.
How can I define an object with explicit class name, so that I can use it?
You could always use ObjectName.type. For instance:
trait Test
object A extends Test
def test(a: A.type) = a
test(A) // compiles fine
test(new Test{}) // compilation error
Note that in case of object ABC extends Enumeration{...} you should use ABC.Value as type of instances:
object ABC extends Enumeration{ val A, B, C = Value}
def test(a: ABC.Value) = a
scala> test(ABC.A)
res0: ABC.Value = A

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

Scala object for importing all methods

I'm trying to import a bunch of methods from one class to another without extending it. I've made it work but why one approach works and the other doesn't is beyond me.
Stripped down, here is what I'm trying to do
class A {def x() {println("x")}}
object A
class B {
import A._
def y() {x()}
}
And the compiler tells me "not found: value x"
But it works if I do either this
class C extends A
class B {
import C._
or if I do this
object C extends A
class B {
import C._
Can someone explain why this is the case?
The reason why your code example class C extends A is not working is that you import class members which can only exist in the class they are defined.
Whereas when you write object C extends A you will create a singleton (in Scala called object like the keyword) which represents an instance and allows you to import its members.
So, to make members of other classes visible you always have to extend them, either by an object or by another class/trait. It is not enough to declare a companion object of a class because it does not hold an instance of its companion class.
There also the possibility of using implicits.
You need to have a way to get from a instance of B to the desired instance of
A. In the example below I use a member value, but it should be possible to make
it a function as well.
The trait exposed exposes the this in B to the implicits declared in A.
The trait PathTo can be used to expose a path to the desired instance of A.
class A {
def a1(){ println("a1") };
def a2(){ println("a2") };
def a3(){ println("a3") };
}
object A{
def a1()(implicit a:A){a.a1};
def a2()(implicit a:A){a.a2};
def a3()(implicit a:A){a.a3};
//makes it possible to use a1() instead of a1()(this.a)
implicit def insertPathToA(implicit path:PathTo[A]):A=path.pathTo;
// Makes it possible to write this.a2() instead of this.a.a2();
implicit def convertPathToA(path:PathTo[A]):A=path.pathTo;
};
trait exposed[U]{
implicit def self:U=this.asInstanceOf[U];
}
trait PathTo[U]{
implicit def pathTo:U;
}
class B(val a:A) extends exposed[B] with PathTo[A] {
// imports the magic
import A._
override def pathTo:A=a;
def y() {
a1() ;
this.a2();
};
}