Scala. Making a class generic - scala

I have this code which appears over and over in my project for each type of class we serialize to Avro
class FooKryoRegistrator extends KryoRegistrator {
override def registerClasses(kryo: Kryo) {
kryo.register(classOf[Foo], SpecificRecordBinarySerializer(classTag[Foo]))
kryo.register(classOf[GenericData.Array[_]], new SpecificInstanceCollectionSerializer(classOf[java.util.ArrayList[_]]))
}
}
Now instead of having to write this Registrator class for each and every entity (Foo, Bar, Baz.....) in my project, I thought it will be better to make this generic. So I did
class GenericKryoRegistrator[T] extends KryoRegistrator {
override def registerClasses(kryo: Kryo) {
kryo.register(classOf[T], SpecificRecordBinarySerializer(classTag[T]))
kryo.register(classOf[GenericData.Array[_]], new SpecificInstanceCollectionSerializer(classOf[java.util.ArrayList[_]]))
}
}
But I get a compile time error
class type required but T found
I googled on this error and found a recommendation that I should use ClassTag instead of class. So I changed the implementation to
class GenericKryoRegistrator[T] extends KryoRegistrator {
override def registerClasses(kryo: Kryo) {
kryo.register(classTag[T].runtimeClass, SpecificRecordBinarySerializer(classTag[T]))
kryo.register(classOf[GenericData.Array[_]], new SpecificInstanceCollectionSerializer(classOf[java.util.ArrayList[_]]))
}
}
but now it says
No ClassTag available for T

If you take the class tag as an implicit argument to your class, you can then use it:
class GenericKryoRegistrator[T] (implicit ct: ClassTag[T]) extends KryoRegistrator {
override def registerClasses(kryo: Kryo) {
kryo.register(ct.runtimeClass, SpecificRecordBinarySerializer(ct))
kryo.register(classOf[GenericData.Array[_]], new SpecificInstanceCollectionSerializer(classOf[java.util.ArrayList[_]]))
}
}

Related

Stack Modification Traits in Scala Not Working

Scala Compiler giving error where trying to run following program.
Error:(19, 8) class Logging inherits conflicting members:
method log in trait TimestampLogger of type (msg: String)Unit and
method log in trait ShortLogger of type (msg: String)Unit
(Note: this can be resolved by declaring an override in class Logging.)
class Logging extends TimestampLogger with ShortLogger
^
trait ShortLogger {
def log (msg: String) {println(msg)}
trait TimestampLogger {
def log (msg: String) {
println("We are in Timestamp Logger")
println(new java.util.Date() )
}
}
class Logging extends TimestampLogger with ShortLogger
val a = new Logging
a.log("Log Message")
Why Stackable Modification in scala traits not suggesting the correct log method?
Why are we getting compilation error?
The error here is as message says lack of overrides.
You cannot have 2 different implementations of a method with the same signature. You have to resolve it. With traits you can have one implementation override another - this is actually required to perform trait linearization. But to be able to override you have to prove that overrides are about the same method. One way to fix it is to let methods override some base member. It always picks the "last" implementation.
trait Logger { def log(msg: String): Unit = () }
trait ShortLogger extends Logger {
override def log(msg: String) = println(msg)
}
trait TimestampLogger extends Logger {
override def log(msg: String): Unit = {
println("We are in Timestamp Logger")
println(new java.util.Date() )
}
}
// last override "wins" => ShortLogger implementation will be used
class Logging1 extends TimestampLogger with ShortLogger
// last override "wins" => TimestampLogger implementation will be used
class Logging2 extends ShortLogger with TimestampLogger
If you don't want to use last-wins, you have to reimplement the method in the place where they are conflicting:
class Logging extends TimestampLogger with ShortLogger {
override def log(msg: String) = ...
}
If you wanted to have both functionalities you would have to use a former approach + super
trait Logger { def log(msg: String): Unit = () }
trait ShortLogger extends Logger {
override def log(msg: String) = {
super.log(msg)
println(msg)
}
}
trait TimestampLogger extends Logger {
override def log(msg: String): Unit = {
super.log(msg)
println("We are in Timestamp Logger")
println(new java.util.Date())
}
}
// both will perform both loggings, but in a different order
class Logging1 extends TimestampLogger with ShortLogger
class Logging2 extends ShortLogger with TimestampLogger

Scala generics function call

I have the following trait in scala:
trait BaseDao {
type T <: BaseModel
def saveModel(model: T)
}
I created a class which extends BaseDao:
class Sample (dynamoDBMapper: DynamoDBMapper) extends BaseDao with LazyLogging {
checkNotNull(dynamoDBMapper)
protected def classType: Class[T] = implicitly[ClassTag[T]].runtimeClass.asInstanceOf[Class[T]]
override def saveModel(model: T): Unit ={
model.validate()
dynamoDBMapper.save(model)
}
Now, when I create the instance of above class and try to call save method:
val testModel = new TestModel();
testModel.setHashKey("a")
testModel.setSortKey("b")
testModel.setCreatedOn(new Date())
testModel.setModifiedOn(new Date())
sample.saveModel(testModel)
It gives the following error:
Type mismatch expected: Sample#T, actual: TestModel model class extends BaseModel class
I am new in scala and I am not able to figure out what is wrong here?
You haven't defined type T in Sample.
Rewrite your Sample class to look somewhat like this:
class Sample (dynamoDBMapper: DynamoDBMapper) extends BaseDao with LazyLogging {
checkNotNull(dynamoDBMapper)
type T = TestModel
override def saveModel(model: T): Unit ={
model.validate()
dynamoDBMapper.save(model)
}
}

Scala implicitly extend an interface

How can I make arbitrary type T to conform to trait Run without having inherit the trait? Type class works at method level but class is expecting type Run and I cannot change method signature of run() as it is overriding an interface.
trait Run[T] {
def run(): Unit
}
class SomeClass(runner: Run[_]) extends Runnable {
#override def run() {
runner.run()
}
}
Current solution:
class SomeRunnable(someRunnable: SomeType) {
#override def run(){
someRunabble.someMethod()
}
}

Referencing the parent class inside a Trait

I have a class that extends a Trait and I want to write Traits that can mix in with the class and override some of the methods.
The trait that my class is extending looks like this
trait CharSource {
def source: Iterator[Char]
def words: Iterator[String] = {
while(source.hasNext){
//Logic to get the next word from a Char Iterator
}
}
final def chars: Iterator[Char] = words.toString().toIterator
}
The class that extends CharSource
class IteratorDocumentSource(iterator: Iterator[Char]) extends CharSource {
def source = iterator
}
Now I want to write a trait to override the source def in IteratorDocutmentSource for some special behavior
trait PunctuationRemover extends Transformer {self: CharSource =>
override
/** Character source. Overriding should be in terms of `super.source` for
stackability. */
abstract val source: Iterator[Char] = {
super.source
//additional logic ...
}
}
The transformer trait that PunctioationRemover extends
trait Transformer {self: CharSource =>
protected def source: Iterator[Char]
def words: Iterator[String]
}
I get an error when making this call
new IteratorDocumentSource("Hello World!".iterator) with PunctuationRemover
Error:
An exception or error caused a run to abort:
SampleSuite$$anonfun$2$$anon$3.document$PunctuationRemover$$super$source()Lscala/collection/Iterator;
java.lang.AbstractMethodError:
SampleSuite$$anonfun$2$$anon$3.document$PunctuationRemover$$super$source()Lscala/collection/Iterator;
I referenced this post but I think my situation is a little different
Can I override a scala class method with a method from a trait?

Scala 2.11 override things form an abstract class

I have a question concerning Scala override (as my title suggests)
Now I have the following classes/traits:
trait FSM {def transitionGraph:Map[String,(JsValue,FSM)]
abstract class AClass: FSM { def transitionGraph }
class Class extends AClass{ override def transitionGraph ... } <-- Wont work
trait OverrideTrait extends AClass { abstract override def transitionGraph } <-- works
class NewClass extends OverrideTrait { } <--- Works, I can use the overridden transitionGraph
My question is: Why can I not override things from an abstract class. Is it because I am never allowed to instantiate an abstract class. Thus the behavior :
val AClass class = new Class
is never allowed to happen?
Thanks.
There seems to be a lot of stuff omitted from the code you've given, so I'm not sure I get the question, but here's something similar that does compile:
trait FSM { def transitionGraph: String }
abstract class AClass extends FSM { def transitionGraph: String }
class Class extends AClass { override def transitionGraph = ??? }
trait OverrideTrait extends AClass { override def transitionGraph = ??? }
class NewClass extends OverrideTrait { }
Does this help at all?
Your code example wouldn't compile. But it should work once you corrected a few things:
trait FSM {def transitionGraph:Map[String,(JsValue,FSM)]}
abstract class AbstractClass extends FSM { def transitionGraph }
class ConcreteClass extends AbstractClass{ def transitionGraph = ??? }
val someClass: AbstractClass = new ConcreteClass