Scala trait override method with multiple parameters - scala

I would love to create trait called filter with method execute and force all children to have execute but in some filters execute may need some other parameters and some don't.
Is here any way how to create child with different parameters and parent ?
Maybe pattern matching could be solution in some way. Also Im new user of Scala so I ll be happy for all advices
Example code:
trait filter{
def execute (photo: Photo): Photo
}
object FooFilter{
// Here we will get compile error due that execute method is not overloading anything
override def execute (photo: Photo, foo: Foo): Photo = {...}
}

Related

Proper use of Scala traits and case objects

Trying to get the hang of Scala classes and traits, here's a simple example. I want to define a class which specifies a variety of operations, that could be implemented in lots of ways. I might start with,
sealed trait Operations{
def add
def multiply
}
So for example, I might instantiate this class with an object does that add and multiply very sensibly,
case object CorrectOperations extends Operations{
def add(a:Double,b:Double)= a+b
def multiply(a:Double,b:Double)= a*b
}
And also, there could be other ways of defining those operations, such as this obviously wrong way,
case object SillyOperations extends Operations{
def add(a:Double,b:Double)= a + b - 10
def multiply(a:Double,b:Double)= a/b
}
I would like to pass such an instance into a function that will execute the operations in a particular way.
def doOperations(a:Double,b:Double, op:operations) = {
op.multiply(a,b) - op.add(a,b)
}
I would like doOperations to take any object of type operations so that I can make use of the add and multiply, whatever they may be.
What do I need to change about doOperations, and what am I misunderstanding here? Thanks
Haven't ran your code, but I suppose you got a compilation error.
If you don't define the signature of the methods in the Operations trait, then by default it will be interpreted as () => Unit.
This means that the methods in the inheriting objects are not really overriding the methods in the trait, but define overloads instead. See more about that here. You can verify this by writing override in front of the method definitions in the object methods. That will force the compiler to explicitly warn you that the methods are not overriding anything from the ancestor trait, and works as a "safety net" against similar mistakes.
To fix the bug, spell out the signature of the trait like the following:
sealed trait Operations{
def add(a:Double,b:Double):Double
def multiply(a:Double,b:Double):Double
}
In fact, the output parameter types are not even necessary in the methods of the inheriting objects (but note the added override attributes):
case object CorrectOperations extends Operations{
override def add(a:Double,b:Double) = a+b
override def multiply(a:Double,b:Double) = a*b
}

Scala Akka - generics type in receive handler

I am trying to get my head around on what is best way to code this implementation. To give you example, here is my DAO handler code looks like
trait IDAOHandler[+T] {
def create[U <: AnyRef: Manifest](content: U): Try[String]
}
class MongoDAOHAndler extends IDAOHandler[+T]...
So I am creating actor that will handle all my persistence task that includes serializing the content and updating MongoDB database.
So I am using akka and the trick is in receive method, how do i handle generics type parameter. Even though my actor code is non-generic, but the messages it is going to receive will be generic type and based on content type in createDAO I was planning to get appropriate DAO handler (described aboe) and invoke the method.
case class createDAO[T](content: T) (implicit val metaInfo:TypeTag[T])
class CDAOActor(daofactory: DAOFactory) extends BaseActor {
def wrappedReceive = {
case x: createDAO[_] => pmatch(x)
}
def pmatch[A](c: createDAO[A]) {
//getting dao handler which will not work because it needs manifest
}
}
Let me know if there are any other ways to re-write this implementation.
You might already know this, but a little background just to be sure: In Scala (and Java) we have what is called type erasure, this means that the parametric types are used to verify the correctness of the code during compile time but is then removed (and "does not give a runtime cost", http://docs.oracle.com/javase/tutorial/java/generics/erasure.html). Pattern matching happens during runtime so the parametric types are already erased.
The good news is that you can make the Scala compiler keep the erased type by using TypeTag like you have done in your case class or ClassTag which contains less information but also keeps the erased type. You can get the erased type from the method .erasure (.runtimeClass in Scala 2.11) which will return the Java Class of the T type. You still wont be able to use that as the type parameter for a method call as that again happens compile time and you are now looking at that type in runtime, but what you can do is to compare this type during runtime with if/else or patternmatching.
So for example you could implement a method on your daofactory that takes a Class[_] parameter and returns a DAO instance for that class. In pmatch you would then take the erased type out of the tag and pass on to it.
Here is some more info about the tags, why they exist and how they work:
http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html
I took a bit different approach, kind of dispatcher pattern, so here is the revised code
trait IDAOProcess
{
def process(daofactory:IDAOFactory,sender:ActorRef)
}
case class createDAO[T <: AnyRef : Manifest](content:T) (implicit val metaInfo:TypeTag[T]) extends IDAOProcess
{
def process(daofactory:IDAOFactory,sender:ActorRef)
{
for ( handler <- daofactory.getDAO[T] )
{
handler.create(content)
}
}
}
class DAOActor(daofactory:IDAOFactory) extends BaseActor
{
def wrappedReceive =
{
case x:IDAOProcess =>
{
x.process(daofactory,sender)
}
}
}

Scala testing Mailer.sendEmailClientSuspended

I have the following bit of code below and need to test the email is sent when a user is suspended.
def suspendClient(client: Client, event: Event): EventResult = {
Logger.debug(String.format(s"Found Client[${client.getName}]"));
subService.suspend(client)
Mailer.sendEmailClientSuspended(client)
WebHookEventDAO.completeEvent(event.getId)
EventResult.ok
}
The main bit of logic i'm trying to test is Mailer.sendEmailClientSuspended(client) is invoked with the correct args e.g the correct Client is passed. Is it worth splitting it up into a seperate function and how difficult is it to test a 'Object' in Scala since Mailer is an Object.
Assuming you're writing your tests in Scala with MockitoSugar and ScalaTest you want to be using an ArgumentCaptor from the Mockito library. This allows you to capture the value of the client object passed as the parameter to the fundtion sendEmailClientSuspended(client).
See this stackoverflow post for a worked example you can follow. You'll need to specify the package your Client class is in, so something like this...
val capturedClient = ArgumentCaptor.forClass(classOf[com.acme.app.Client])
If your Mailer object doesn't extent a Trait currently, add one so you can mock the Trait and call verify() on it.
If you don't own the code to Mailer, you can move the call out into it's own helper class that you write, and you can then mock the new Trait. Something like this...
trait MailerTrait {
def sendEmailClientSuspended(client: Client): Unit
}
object MyMailer extends MailerTrait () {
def sendEmailClientSuspended(client: Client): Unit = {
Mailer.sendEmailClientSuspended(client)
}
}

How to design immutable model classes when using inheritance

I'm having trouble finding an elegant way of designing a some simple classes to represent HTTP messages in Scala.
Say I have something like this:
abstract class HttpMessage(headers: List[String]) {
def addHeader(header: String) = ???
}
class HttpRequest(path: String, headers: List[String])
extends HttpMessage(headers)
new HttpRequest("/", List("foo")).addHeader("bar")
How can I make the addHeader method return a copy of itself with the new header added? (and keep the current value of path as well)
Thanks,
Rob.
It is annoying but the solution to implement your required pattern is not trivial.
The first point to notice is that if you want to preserve your subclass type, you need to add a type parameter. Without this, you are not able to specify an unknown return type in HttpMessage
abstract class HttpMessage(headers: List[String]) {
type X <: HttpMessage
def addHeader(header: String):X
}
Then you can implement the method in your concrete subclasses where you will have to specify the value of X:
class HttpRequest(path: String, headers: List[String])
extends HttpMessage(headers){
type X = HttpRequest
def addHeader(header: String):HttpRequest = new HttpRequest(path, headers :+header)
}
A better, more scalable solution is to use implicit for the purpose.
trait HeaderAdder[T<:HttpMessage]{
def addHeader(httpMessage:T, header:String):T
}
and now you can define your method on the HttpMessage class like the following:
abstract class HttpMessage(headers: List[String]) {
type X <: HttpMessage
def addHeader(header: String)(implicit headerAdder:HeaderAdder[X]):X = headerAdder.add(this,header) }
}
This latest approach is based on the typeclass concept and scales much better than inheritance. The idea is that you are not forced to have a valid HeaderAdder[T] for every T in your hierarchy, and if you try to call the method on a class for which no implicit is available in scope, you will get a compile time error.
This is great, because it prevents you to have to implement addHeader = sys.error("This is not supported")
for certain classes in the hierarchy when it becomes "dirty" or to refactor it to avoid it becomes "dirty".
The best way to manage implicit is to put them in a trait like the following:
trait HeaderAdders {
implicit val httpRequestHeaderAdder:HeaderAdder[HttpRequest] = new HeaderAdder[HttpRequest] { ... }
implicit val httpRequestHeaderAdder:HeaderAdder[HttpWhat] = new HeaderAdder[HttpWhat] { ... }
}
and then you provide also an object, in case user can't mix it (for example if you have frameworks that investigate through reflection properties of the object, you don't want extra properties to be added to your current instance) (http://www.artima.com/scalazine/articles/selfless_trait_pattern.html)
object HeaderAdders extends HeaderAdders
So for example you can write things such as
// mixing example
class MyTest extends HeaderAdders // who cares about having two extra value in the object
// import example
import HeaderAdders._
class MyDomainClass // implicits are in scope, but not mixed inside MyDomainClass, so reflection from Hiberante will still work correctly
By the way, this design problem is the same of Scala collections, with the only difference that your HttpMessage is TraversableLike. Have a look to this question Calling map on a parallel collection via a reference to an ancestor type

extending scala collections for a specific member type

I want to do something like
class Pack extends collection.immutable.List[Dog]{
def pullSled() = //...
}
But the Scala compiler tells me
illegal inheritance from sealed class List
This would be trivial to do in Java, but I think there is something key I am missing.
Motivations:
I want to be able to use all the base class methods
(new Pack()).contains(snoopy)
I want to be able to extend it, either directly or with mixins
new Pack() with Driver
I would like to be able to change the underlying collection type simply (to switch to a Set for instance)
Thanks!
List[T] is final, hence you cannot extend from it (see why below). If you just need an additional method on a List[Dog], easiest is probably to pimp it:
implicit class Pack(l: List[Dog]) {
def pullSled() = //...
}
If Pack is in scope, the following will work:
val a = List(new Dog)
a.pullSled()
If you really need to create your own collection of dogs, have a look here:
http://www.scala-lang.org/docu/files/collections-api/collections-impl.html
You cannot extend from List[T] because of the following: Suppose you have Pack as you would like to have it, now the following will work, but not really give you what you want:
val pack: Pack = ...
val pack2 = new Dog :: pack
// pack2: List[Dog], not a Pack... :(
Properly extending from LinearSeq as described in the upper link will mitigate this.