Scala forward or delegate methods to encapsulated object - scala

Is there any possibility to implicitly forward some of class methods to encapsulated object?
case class Entity(id: Int, name: String,) {
private lazy val lastScan = new LastScan
def getLastScanDate = lastScan.getLastScanDate
def updateLastScanDate = lastScan.updateLastScanDate
}
I want to avoid creating def updateLastScanDate = lastScan.updateLastScanDate just to forward methods to wrapped object.

In the plain language this is not possible. There used to be a compiler plugin by Kevin Wright to achieve this automatic delegation.
He seems to be working on an Autorproxy "Rebooted" version now that is macro based, making it straight forward to include in your project. I'm pasting here an example from its test sources:
trait Bippy {
def bippy(i : Int): String
}
object SimpleBippy extends Bippy {
def bippy(i: Int) = i.toString
}
#delegating class RawParamWrapper(#proxy pivot: Bippy)
val wrapper = new RawParamWrapper(SimpleBippy)
assert(wrapper.bippy(42) == "42")

Related

Way to enhance a class with function delegation

I have the following classes in Scala:
class A {
def doSomething() = ???
def doOtherThing() = ???
}
class B {
val a: A
// need to enhance the class with both two functions doSomething() and doOtherThing() that delegates to A
// def doSomething() = a.toDomething()
// def doOtherThing() = a.doOtherThing()
}
I need a way to enhance at compile time class B with the same function signatures as A that simply delegate to A when invoked on B.
Is there a nice way to do this in Scala?
Thank you.
In Dotty (and in future Scala 3), it's now available simply as
class B {
val a: A
export a
}
Or export a.{doSomething, doOtherThing}.
For Scala 2, there is unfortunately no built-in solution. As Tim says, you can make one, but you need to decide how much effort you are willing to spend and what exactly to support.
You can avoid repeating the function signatures by making an alias for each function:
val doSomething = a.doSomething _
val doOtherthing = a.doOtherThing _
However these are now function values rather than methods, which may or may not be relevant depending on usage.
It might be possible to use a trait or a macro-based solution, but that depends on the details of why delegation is being used.
Implicit conversion could be used for delegation like so
object Hello extends App {
class A {
def doSomething() = "A.doSomething"
def doOtherThing() = "A.doOtherThing"
}
class B {
val a: A = new A
}
implicit def delegateToA(b: B): A = b.a
val b = new B
b.doSomething() // A.doSomething
}
There is this macro delegate-macro which might just be what you are looking for. Its objective is to automatically implement the delegate/proxy pattern, so in your example your class B must extend class A.
It is cross compiled against 2.11, 2.12, and 2.13. For 2.11 and 2.12 you have to use the macro paradise compile plugin to make it work. For 2.13, you need to use flag -Ymacro-annotations instead.
Use it like this:
trait Connection {
def method1(a: String): String
def method2(a: String): String
// 96 other abstract methods
def method100(a: String): String
}
#Delegate
class MyConnection(delegatee: Connection) extends Connection {
def method10(a: String): String = "Only method I want to implement manually"
}
// The source code above would be equivalent, after the macro expansion, to the code below
class MyConnection(delegatee: Connection) extends Connection {
def method1(a: String): String = delegatee.method1(a)
def method2(a: String): String = delegatee.method2(a)
def method10(a: String): String = "Only method I need to implement manually"
// 96 other methods that are proxied to the dependency delegatee
def method100(a: String): String = delegatee.method100(a)
}
It should work in most scenarios, including when type parameters and multiple argument lists are involved.
Disclaimer: I am the creator of the macro.

Scala generic type with constraints

I am tinkling with Scala and would like to produce some generic code. I would like to have two classes, one "outer" class and one "inner" class. The outer class should be generic and accept any kind of inner class which follow a few constraints. Here is the kind of architecture I would want to have, in uncompilable code. Outer is a generic type, and Inner is an example of type that could be used in Outer, among others.
class Outer[InType](val in: InType) {
def update: Outer[InType] = new Outer[InType](in.update)
def export: String = in.export
}
object Outer {
def init[InType]: Outer[InType] = new Outer[InType](InType.empty)
}
class Inner(val n: Int) {
def update: Inner = new Inner(n + 1)
def export: String = n.toString
}
object Inner {
def empty: Inner = new Inner(0)
}
object Main {
def main(args: Array[String]): Unit = {
val outerIn: Outer[Inner] = Outer.empty[Inner]
println(outerIn.update.export) // expected to print 1
}
}
The important point is that, whatever InType is, in.update must return an "updated" InType object. I would also like the companion methods to be callable, like InType.empty. This way both Outer[InType] and InType are immutable types, and methods defined in companion objects are callable.
The previous code does not compile, as it is written like a C++ generic type (my background). What is the simplest way to correct this code according to the constraints I mentionned ? Am I completely wrong and should I use another approach ?
One approach I could think of would require us to use F-Bounded Polymorphism along with Type Classes.
First, we'd create a trait which requires an update method to be available:
trait AbstractInner[T <: AbstractInner[T]] {
def update: T
def export: String
}
Create a concrete implementation for Inner:
class Inner(val n: Int) extends AbstractInner[Inner] {
def update: Inner = new Inner(n + 1)
def export: String = n.toString
}
Require that Outer only take input types that extend AbstractInner[InType]:
class Outer[InType <: AbstractInner[InType]](val in: InType) {
def update: Outer[InType] = new Outer[InType](in.update)
}
We got the types working for creating an updated version of in and we need somehow to create a new instance with empty. The Typeclass Pattern is classic for that. We create a trait which builds an Inner type:
trait InnerBuilder[T <: AbstractInner[T]] {
def empty: T
}
We require Outer.empty to only take types which extend AbstractInner[InType] and have an implicit InnerBuilder[InType] in scope:
object Outer {
def empty[InType <: AbstractInner[InType] : InnerBuilder] =
new Outer(implicitly[InnerBuilder[InType]].empty)
}
And provide a concrete implementation for Inner:
object AbstractInnerImplicits {
implicit def innerBuilder: InnerBuilder[Inner] = new InnerBuilder[Inner] {
override def empty = new Inner(0)
}
}
Invoking inside main:
object Experiment {
import AbstractInnerImplicits._
def main(args: Array[String]): Unit = {
val outerIn: Outer[Inner] = Outer.empty[Inner]
println(outerIn.update.in.export)
}
}
Yields:
1
And there we have it. I know this may be a little overwhelming to grasp at first. Feel free to ask more questions as you read this.
I can think of 2 ways of doing it without referring to black magic:
with trait:
trait Updatable[T] { self: T =>
def update: T
}
class Outer[InType <: Updatable[InType]](val in: InType) {
def update = new Outer[InType](in.update)
}
class Inner(val n: Int) extends Updatable[Inner] {
def update = new Inner(n + 1)
}
first we use trait, to tell type system that update method is available, then we put restrains on the type to make sure that Updatable is used correctly (self: T => will make sure it is used as T extends Updatable[T] - as F-bounded type), then we also make sure that InType will implement it (InType <: Updatable[InType]).
with type class:
trait Updatable[F] {
def update(value: F): F
}
class Outer[InType](val in: InType)(implicit updatable: Updatable[InType]) {
def update: Outer[InType] = new Outer[InType](updatable.update(in))
}
class Inner(val n: Int) {
def update: Inner = new Inner(n + 1)
}
implicit val updatableInner = new Updatable[Inner] {
def update(value: Inner): Inner = value.update
}
First we define type class, then we are implicitly requiring its implementation for our type, and finally we are providing and using it. Putting whole theoretical stuff aside, the practical difference is that this interface is that you are not forcing InType to extend some Updatable[InType], but instead require presence of some Updatable[InType] implementation to be available in your scope - so you can provide the functionality not by modifying InType, but by providing some additional class which would fulfill your constrains or InType.
As such type classes are much more extensible, you just need to provide implicit for each supported type.
Among other methods available to you are e.g. reflection (however that might kind of break type safety and your abilities to refactor).

Scala Generics & Reflection Issue

I noticed some gap around reflection and generics and I wonder if anybody can help here.
Let say I have the following abstract class:
abstract class Animal[T : Eatable: ClassTag] {
def eat(food: T) : Unit
}
And here is one implementation of it:
class Dog[DogFood] {
def eat (food: DogFood) : Unit = ???
}
class DogFood extends Eatable
And here I had some method that given an animal, feeds it
def feed[T <: Eatable](animal: Animal[T]) : Unit = {
val isAvailable = Storage.isAvailable[T]
???
}
Now let say I want to instantiate the implementation class using reflection as it is part of my system configuration:
val config = ....
val animalCls = config.getString("animal.type")
val animalInstance = animalCls = Class.forName(animalCls).newInstance
// Issue is here - I can't call this method as it uses classTags!
feed(animalInstance)
A solution might be:
val animalCls = config.getString("animal.type").asIsntanceOf[Animal[_]]
But then the following call inside feed will fail as it doesn't bind the right type:
Storage.isAvailable[T]
Any ideas here?

Scala syntactic sugar for transparently invoking a unary apply on a companion object

class OpenNLPAnnotator extends ThreadLocal[OpenNLPAnnotatorInstance] {
override def initialValue = new OpenNLPAnnotatorInstance
}
object OpenNLPAnnotator {
private lazy val ann_ = new OpenNLPAnnotator
private def ann = ann_
def apply = ann.get()
}
Is there any way for me to get the TLV by doing OpenNLPAnnotator.someMethodOnTheTLV ? I have to write OpenNLPAnnotator.apply.someMethodOnTheTLV
edit
Based on the answers below i'm thinking something like this would be nicest
object OpenNLPAnnotator {
private lazy val ann_ = new OpenNLPAnnotator
private def ann = ann_
def apply() = ann.get()
def annotator = ann.get
}
Then I could just do annotator.whatever.
That would require an import of course, so unless I put it in a package object it's swings and round-a-bouts. Though I haven't used package objects yet and do not understand the ins and outs.
The only way to call apply method implicitly is to add parentheses after object name like this:
OpenNLPAnnotator().someMethodOnTheTLV
But you have to change apply method declaration (add parentheses):
def apply() = ann.get()
Nasty hack
You could create an implicit conversion from OpenNLPAnnotator.type to OpenNLPAnnotator like this:
implicit def nastyHack(o: OpenNLPAnnotator.type): OpenNLPAnnotator = o.apply
So you could call all methods of OpenNLPAnnotator on companion object.
OpenNLPAnnotator.someMethodOnTheTLV will be converted to this:
nastyHack(OpenNLPAnnotator).someMethodOnTheTLV
Note (in response to your edit):
You could rename apply method while importing it:
import OpenNLPAnnotator.{apply => annotator}
You have two options:
Wait for me to rewrite autoproxy using macros (it'll be done around the same time that scala 2.11.0-RC1 is released)
Use a different pattern!
Did you know that singletons can inherit from their companions?
class OpenNLPAnnotator extends ThreadLocal[OpenNLPAnnotatorInstance] {
override def initialValue = new OpenNLPAnnotatorInstance
}
object OpenNLPAnnotator extends OpenNLPAnnotator {
def apply = this.get()
}

Inject a dependency inside an object

I'm new to the Play framework and scala and I'm trying to inject a dependency inside a companion object.
I have a simple case class, like:
case class Bar(foo: Int) {}
With a companion object like:
object Bar {
val myDependency =
if (isTest) {
// Mock
}
else
{
// Actual implementation
}
val form = Form(mapping(
"foo" -> number(0, 100).verifying(foo => myDependency.validate(foo)),
)(Bar.apply)(Bar.unapply))
}
This works fine, but it's not really a clean way to do it. I'd like to be able to inject the dependency at build time so that I can inject different mock objects when testing and different real implementations in development and production.
What's the best way to achieve this?
Any help really appreciated. Thanks!
Along the lines of the Cake, we can try to change your example to
trait Validator {
def validate(foo: Int): Boolean
}
trait TestValidation {
val validator = new Validator {
def validate(foo: Int): Boolean = ...
}
}
trait ImplValidation {
val validator = new Validator {
def validate(foo: Int): Boolean = ...
}
}
trait BarBehavior {
def validator: Validator
val form = Form(mapping(...))(Bar.apply)(Bar.unapply)
}
//use this in your tests
object TestBar extends BarBehavior with TestValidation
//use this in production
object ImplBar extends BarBehavior with ImplValidation
You should additionally try and test if this example fits well within the Play Framework, too