How pass implicit parameters in akka with inheritance? - scala

Let's begin with class structure
The class structure
Base abstract class
abstract class BaseCass {
def someFunction() : Any
//Here is the place where someFunction is called
startUpMethod = {
someFunction()
}
}
Base implemetation
import Utility._
class BaseImpelmentation {
//These parameters are not passed into method calls
implicit object ParameterOne = ParameterOne
implicit object ParameterSecond = ParameterSecond
implicit object ParameterThird = ParameterThird
def someFunction() : Any = {
functionWithImplicitOne();
functionWithImplicitSecond();
functionWithImplicitThird();
}
}
Class with implicit functions
class Utility {
//here all function with implicit are defined.
}
The algorithm is
someFunction is called at class initialization e.g. it called after constructor, but before any other methods in class
someFunction overrided in BaseImpelmentation
BaseImpelmentation imports function with implicit parameters from Utility class.
The problem
When someFunction is called in BaseClass implicit parameters from BaseImpelmentation are not used. So I have to place them in BaseCass. But in that case I place a piece of implementation to abstract class which is not very good.
Is it possible to place implicit parametrs into BaseImpelmentation but do not pass them as usual parameters?

If someFunction is only called when the class is fully constructed then this should work; the call to functionWithImplicitOne() in BaseImpelmentation[sic] will use ParameterOne, because it is in scope where the method is called. Your problem is something else. What is the actual error message?

Related

When does the constructor of a Scala user-defined annotation class gets executed?

I defined a Scala class MyAnnotation, used to annotate certain classes within my program:
case class MyAnnotation() extends scala.annotation.StaticAnnotation {
println("MyAnnotation initialized") // doesn't get printed
}
Which is used in the following way:
#MyAnnotation()
class MyClass() {
...
}
However, when I instantiate the MyClass class, the constructor of MyAnnotation doesn't get executed. I.e., the println does not happen.
val x = new MyClass()
// nothing gets printed
Sumarized: is there any way to provide a constructor to a user-defined annotation class that gets executed when another class annotated with that annotation is instantiated?

Can't invoke method in class' "this" method

I'm running into
error: not found: value defineParser
[scalac-2.11] def this(format: String) = this(format, defineParser(format))
when I try to call a method in the this method of a class in order to dynamically return a parser depending on the format.
The class entire structure looks like so:
class TimestampConversion(format: String, parser: DSVTimestampFormatter) extends ObjectConversion[Any] with FormattedConversion[DSVTimestampFormatter] {
def defineParser(format: String): DSVTimestampFormatter = {
// hidden implementation details
}
def this(format: String) = this(format, defineParser(format))
}
And this fails on compiling this class. Why am I not able to invoke the defineParser method? It's well defined there.
It's OK to define a secondary constructor, but it's slightly more idiomatic to add apply factory methods to the companion object instead.
It's also possible to add a default arg for the parameter in the primary constructor, where it's more obvious what the scope is:
class C(format: String)(parser: Parser = C.defineParser(format))
object C { private def defineParser(format: String): Parser = ??? }
Here is the spec language (section 5.3.1) saying that the scope for your this invocation is not "inside the braces of the class definition":
The signature and the self constructor invocation of a constructor
definition are type-checked and evaluated in the scope which is in
effect at the point of the enclosing class definition, augmented by
any type parameters of the enclosing class and by any early
definitions of the enclosing template. The rest of the constructor
expression is type-checked and evaluated as a function body in the
current class.

implementing methods of traits with additional implicit parameters

I want an object to implement the trait Iterable and pass an additional implicit parameter to the implemented method:
object MyRepository extends Iterable[Something] {
def iterator(implict entityManager: EntityManager): Iterator[Something] = ...
}
Obviously this doesn't work because the iterator method has no implicit parameter and is hence not implemented by the method shown above.
An example use case is the map method which I want to apply to the repository values:
def get = Action {
Transaction { implicit EntityManager =>
val result = MyRepository.map(s => s ...)
}
}
Is there some way to implement the Iterable trait and capture the implicit pramameter?
Given that Iterable.iterator does not have this implicit in its signature, you cannot expect to be able to implement this method while adding this implicit: that would be another method (specifically, another overload).
However, if MyRepositorywas a class rather than an object, you could capture the implicit in the class constructor.
And if you want to keep the same use style (as in MyRepository.map{ ... } rather than new MyRepository.map{ ... }), what you can do is to provide an implicit conversion from the object to the class.
Here is an example:
object MyRepository {
class MyRepositoryIterable(implicit entityManager: EntityManager) extends Iterable[Something] {
def iterator: Iterator[Something] = ???
}
implicit def toIterable(rep: MyRepository.type)(implicit entityManager: EntityManager): MyRepositoryIterable = new MyRepositoryIterable
}
What happens now when you do MyRepository.map(...) is that the object gets implicitly converted into an instance of MyRepositoryIterable which captures the implicit EntityManager value. The MyRepositoryIterable is the class that actually implements Iterable.

Retaining arguments passed to superclass constructor

In Scala no methods can be invoked on the current instance when the superclass constructor is called. So there is no opportunity for a method to be invoked which will memorise the value that it is returning, in the current instance. How can I retain the arguments produced to give to a superclass constructor, while still using inheritance, as opposed to composition, and without modifying the source code of the class I'm inheriting from?
You can also use
class Foo(arg1: Type1, arg2: Type 2)(
implicit computed: Hidden[(Type3,Type4)] = (new Type3(arg1), new Type4(arg2))
) extends Bar(computed._1, computed._2) { }
given
private[mypackage] class Hidden[A](val value: A) { }
implicit def i_can_hide_things[A](a: A) = new Hidden(a)
implicit def i_can_find_things[A](ha: Hidden[A]) = ha.value
In Scala 2.8 and above, use an early definition:
class Foo(arg1: Type1, arg2: Type2) extends {
val arg3 = new Type3(arg1)
val arg4 = new Type4(arg2)
} with Bar(arg3, arg4)
This works even if Bar is a class rather than a trait.
Create a companion object with a factory method. The factory method computes the arguments to pass them to the superclass constructor. But it doesn't do so directly, of course - it can't. Instead, it calls your primary constructor, which you can make private, like this:
class C private (private val superclassArg: ArgType) extends Super(superclassArg) { ... }
Unfortunately this solution isn't very compositional, because it doesn't allow you to inherit from C. Making the constructor of C public would, but it would still require duplicating code, and you could forget to preprocess the constructor argument. I suppose it depends whether you think it will always be essential for subclasses of C to preprocess the argument in this way.
Intersperse another class (here MemoBar) into the inheritance hierarchy, like this:
class Foo(arg1: Type1, arg2: Type2) extends MemoBar(new Type3(arg1), new Type4(arg2)) {
}
class MemoBar(protected val arg3: Type3, arg4: Type4) extends Bar(arg3, arg4) {}
Then your arg3 and arg4 will be retained and visible only to subclasses of MemoBar (in this case, just Foo, but of course you could reuse MemoBar if you faced the same problem with Bar again).

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.