Can we force all implementations to be singleton (objects)? - scala

Let's say we have an abstract class (same question for traits also):
abstract class TypeParser[C <: Changes : TypeTag] extends Serializable {
val enrichmentType: EnrichmentType
protected def parseChanges(row: Row): C
}
Where implementations look like the following:
object PlaceholderParser extends TypeParser[PlaceholderChanges] {
val enrichmentType: EnrichmentType = PlaceholderType
override protected def parseChanges(row: Row): PlaceholderChanges = ???
}
The above implementation is a singleton, however, it can't be forced to be a singleton for future implementations. So one can simply implement it as a class, for example:
class PlaceholderParser2() extends TypeParser[PlaceholderChanges2] {
val enrichmentType: EnrichmentType = PlaceholderType2
override protected def parseChanges(row: Row): PlaceholderChanges2 = ???
}
Is there any way of forcing implementations to be a singleton?
side question: is there any advantage of forcing it?

To our advantage all objects extend an interface called Singleton.
You can't extend it directly but we can use a Scala feature called self-types to enforce that all subtypes of TypeParser to also be Singletons (i.e. objects)
abstract class TypeParser[C <: Changes : TypeTag] extends Serializable {
self: Singleton =>
...
}

Related

Can singleton object extend a trait?

I want to extend a trait from Scala object and override those methods which are in trait. So my doubt is those methods will become static to that Object
or instance methods, and is this good approach to extend from trait to Scala Object. Please help on this
trait A{
def show:Unit
}
object B extends A{
override def show(): Unit = {
println("inside Object")
}
}
There are no static methods in Scala. object can indeed extend a trait. Overriden methods, like show, do not become static methods, instead they belong to a single instance of B.type. This is the singleton pattern provided by Scala's object definition facility.
Try the following in Scala REPL:
object B
B
It should output something like
res0: B.type = B$#5688722f
Note how the value B has type B.type, so B is just a value/instance, nothing to do with statics.
Hm, I think a common example/usecase of what you've just described is extending the App trait and overriding the main definition.
object test extends App
{
override def main (args: Array[String]): Unit = {
println("Hello, let's get started")
}
}
In general though, why don't you define the class itself to extend the trait?
If you are going to instantiate new instances of B using B() (instead of new B()) it makes sense to do this.
trait A{
def show:Unit
}
object B { // companion aka singleton object
def apply(){
...
}
}
class B extends A{
override def show(): Unit = {
println("inside Object")
}
}

How to "instantiate" an abstract class in the superclass?

I am implementing an extension of ml.Transformer in Spark; but this question is Scala specific. Here is an example object (part of a Class/Object pair):
abstract class UDFTransformer(func: UserDefinedFunction,
inputFieldNames: Seq[String],
outputFieldName: String) extends Transformer with MLWritable with Serializable {
... definitions here ...
}
object UDFTransformer extends MLReadable[UDFTransformer] {
// Since there are no parameters associted with the UDF, there is nothing to save!
class Writer(instance: UDFTransformer) extends MLWriter {
override protected def saveImpl(path: String): Unit = {}
}
abstract protected class Reader extends MLReader[UDFTransformer]
override def read: MLReader[UDFTransformer] = new Reader
override def load(path: String): UDFTransformer = super.load(path)
}
The new Reader does not compile because the class is abstract and cannot be instantiated. But; any child class will have to define it; along with its necessary members. I cannot just make read abstract as well, this gives me a warning Only classes can have declared but undefined methods.
The fundamental problem is that each child class of my UDFTransformer is going to wrap a specific UDF. Therefore, the reader needs to be able to generate a specific UDF object; this can't be declared in the superclass. But this 'factory' belongs in the companion object, not in the abstract class itself.
How can I go about building a companion object for an abstract class that can leave the definition of read undefined?
The normal way to do it is by creating an abstract class or trait for the companion objects. Something like
abstract class UDFTransformerCompanion[T <: UDFTransformer] extends MLReadable[T] {
abstract def read: MLReader[T]
override def load(path: String): T = super.load(path)
}
class SomeTransformer extends UDFTransformer { ... }
object SomeTransformer extends UDFTransformerCompanion[SomeTransformer] {
override def read: MLReader[SomeTransformer] = ...
}
Not sure why you have the load = super.load override, and it doesn't look like you can have a companion object for the UDFTransformer itself, at least not one extending this abstract class.
See GenericTraversableTemplate for a standard library example.

Why is it not possible (in scala) to provide implementation for an abstract override method in the implementing base class

What I would like to do is this:
trait Addable[T]{
def plus(x: T): T
}
trait AddableWithBounds[T] extends Addable[T] {
abstract override def plus(x: T): T = limitToBounds(super.plus(x))
def limitToBounds(x: T): T = ... //Some bounds checking
}
class Impl(num: Int) extends AddableWithBounds[Impl] {
override def plus(x: Impl) = new Impl(num + x.num)
}
Reading through various posts it would seem that the reason this is not possible is that after class linearization the stacked trait is only looking in classes to its right for implementations of super.plus(x: T)
That is a technical argument though and I'm interested in the question: Is there a fundamental reason why the implementation could not be taken from the base class? Because as you can see in this example it is not possible to implement the plus method before knowing the actual data type that needs to be added but afaic implementing bounds checking in a trait seems reasonable.
Just as an idea: If the problem is that in this case it is unclear which plus is being overridden in the base class maybe a scope identifier like
def Addable[Impl].plus(x: Impl) = new Impl(num + x.num)
would help.
I would avoid overriding and reliance on some super/sub-type invocation. Why not just implement plus and ask sub-types to provide an auxiliary abstract method:
trait Addable[T] {
def plus(x: T): T
}
trait AddableWithBounds[T] extends Addable[T] {
final def plus(x: T): T = limitToBounds(plusImpl(x))
protected def plusImpl(x: T): T
def limitToBounds(x: T): T = ??? //Some bounds checking
}
class Impl(num: Int) extends AnyRef with AddableWithBounds[Impl] {
protected def plusImpl(x: Impl): Impl = ???
}
You're asking: if super.f is abstract (or "incomplete") after mixin, please just pick a concrete f to serve. Maybe you're saying, only if there's exactly one such f, and it's defined in the current template.
One problem is that if the abstract f is called during initialization, and calls the concrete f in the subclass, the initializer for the subclass hasn't run yet.
This is common gotcha for template methods. I think the Josh Bloch book says don't do that.
But the person writing the stackable trait has no way of knowing that a super was transformed in this way.

Self-Type with private modifier

I would like to implement a trait with a self-type like the following:
trait HasEquipment {
this: {def loadEquipment: List[Equipment]} =>
//more methods
}
Now i can mix this trait into classes and these classes have to define a "loadEquipment" Method:
case class Course(id: Long) extends HasEquipment {
def loadEquipment: List[Equipment] = {
//implementation
}
}
However I don't want to expose to loadEquipment Method to everyone but only to the trait. So what i would like to do is make loadEquipment private in the Course class so that only the trait has access to it. Making it private prevents the trait from accessing the method.
Is there another way to make loadEquipment only accessible from within the trait?
Not sure why you want a self-type here. An abstract, protected member works just as well:
trait HasEquipment {
protected def loadEquipment: List[Equipment]
}
case class Course(id: Long) extends HasEquipment {
override protected def loadEquipment: List[Equipment] = ???
}
As a side note, structural types in Scala make use of reflection, which is the reason why they're usually avoided.

correct type specification for cloneable-like trait in scala

The question is not about AnyRef.clone(), it is about case with similar semantic.
I'd like to define an interface for classes that may create copy of itself:
trait Cloneable {
def clone() : this.type
}
class Test(val store : Int) extends Cloneable {
def clone() = new Test(store)
}
Path-dependent this.type would not work since this.type is different for the Test class type and for a class extending the Test. The descendant should then override clone method to match its own type.
How should I define type requirement for the Cloneable trait?
I've peeked into scala collections and found here tip: define TestLike trait, that handles type restrictions, and class Test that embodies corresponding trait.
I'd like to avoid unnecessary clumsiness if possible
trying self-recurring pattern as suggested:
trait Cloneable[A <: Cloneable[A]] {
def clone() : A
}
class Store[A <: Cloneable[A]](val store : Int) extends Cloneable[A] {
override def clone() : A = new Store[A](store)
}
failed with error:
Cloneable.scala:6: error: type mismatch;
found : Store[A]
required: A
override def clone() : A = new Store[A](store)
another issue in the recurring template: premature finalization
class Store(val store : Int) extends Cloneable[Store] {
override def clone() = new Store(store)
}
class SubStore(store : Int, val stash : Double) extends Store(store)
val ss1 = new SubStore(1, 0.5)
val ss2 = ss1.clone()
assert(ss2.isInstanceOf[SubStore])
The issue with SubStore is with type system ignoring absent clone() method in the SubStore class although SubStore is the Cloneable descendant via Store. But the Store finalize Cloneable interface with type parameter Store and all its descendants lacks proper clone() method restriction
Scala type variance allows to you implement what you need in a simple way, but you have to move away from inheritance and go to typeclasses.
trait Cloner[A]{
def cloneObject(input:A):A
}
trait CloningFunctions{
def cloneObject[A](input:A)(implicit cloner:Cloner[A]) = cloner.cloneObject(input)
}
object CloningFunctions extends CloningFunctions
class MyClass1(val b:Int)
class MyClass2(val a:Int,b:Int) extends MyClass1(b)
object Example {
implicit val cloner = new Cloner[MyClass1]{
def cloneObject(input: MyClass1): MyClass1 = new MyClass1(input.b)
}
import CloningFunctions._
cloneObject(new MyClass2(3,4))
}
The idea here is that since Cloner[A] is invariant in type A, the following code won't compile:
could not find implicit value for parameter cloner: Cloner[MyClass2]
cloneObject(new MyClass2(3,4))
because you have a Cloner[MyClass1] but not a Cloner[MyClass2] in scope.
While cloneObject(new MyClass1(3)) will compile.