Extend generic type - PriorityQueue - scala

I can't understand why I need () and hence where MyTypeQueOrdering goes.
Here is header of PriorityQueue, found on official github:
class PriorityQueue[A](implicit val ord: Ordering[A])
Here is my try (which works):
class MyType{
}
object MyTypeQueOrdering extends Ordering[MyType]{
def compare (n1:MyType, n2:MyType) = -1
}
class MyTypeQue extends PriorityQueue[MyType]()(MyTypeQueOrdering){
}
... but I can't figure out why I need (). Does PriorityQueue[MyType]() return something?

Try making MyTypeQueOrdering an implicit object:
object Implicits {
//implicit objects can't be top-level ones
implicit object MyTypeQueOrdering extends Ordering[MyType] {
def compare(n1: MyType, n2: MyType) = -1
}
}
This way you can omit both parentheses:
import Implicits._
class MyTypeQue extends PriorityQueue[MyType] { ... }
The reason you need the empty parentheses in your example is because PriorityQueue[MyType](MyTypeQueOrdering) would assume you're trying to pass the ordering as a constructor parameter. So that's why you need to explicitly show no-arg instantiation and then passing the ordering

Related

Modify constructor arguments before passing it to superclass constructor in Scala

I have a superclass:
class Filter(val param: ComplexFilterParams){
def this(config: String) = this(parseStrConfig(config))
And I need to create a subclass that gets a String argument and then parses it in another way and creates ComplexFilterParams.
Something like that:
class NewFilter(str:String) extends Filter {
Is there a way to do it?
I got one solution. But I think it's ugly. I create companion object, define there a convert method and do next:
class NewFilter(str:String) extends Filter(NewFilter.convert(str)) {
You can go mush easier with another apply implementation in companion object like:
class NewFilter(val param: ComplexFilterParams) extends Filter(param){
//other implementations
}
object NewFilter {
def apply(str: String) = new NewFilter(convert(str))
def convert(str: String): ComplexFilterParams = ...
}
val filter = NewFilter("config string")

Context bounds for type members or how to defer implicit resolution until member instantiation

In the following example, is there a way to avoid that implicit resolution picks the defaultInstance and uses the intInstance instead? More background after the code:
// the following part is an external fixed API
trait TypeCls[A] {
def foo: String
}
object TypeCls {
def foo[A](implicit x: TypeCls[A]) = x.foo
implicit def defaultInstance[A]: TypeCls[A] = new TypeCls[A] {
def foo = "default"
}
implicit val intInstance: TypeCls[Int] = new TypeCls[Int] {
def foo = "integer"
}
}
trait FooM {
type A
def foo: String = implicitly[TypeCls[A]].foo
}
// end of external fixed API
class FooP[A:TypeCls] { // with type params, we can use context bound
def foo: String = implicitly[TypeCls[A]].foo
}
class MyFooP extends FooP[Int]
class MyFooM extends FooM { type A = Int }
object Main extends App {
println(s"With type parameter: ${(new MyFooP).foo}")
println(s"With type member: ${(new MyFooM).foo}")
}
Actual output:
With type parameter: integer
With type member: default
Desired output:
With type parameter: integer
With type member: integer
I am working with a third-party library that uses the above scheme to provide "default" instances for the type class TypeCls. I think the above code is a minimal example that demonstrates my problem.
Users are supposed to mix in the FooM trait and instantiate the abstract type member A. The problem is that due to the defaultInstance the call of (new MyFooM).foo does not resolve the specialized intInstance and instead commits to defaultInstance which is not what I want.
I added an alternative version using type parameters, called FooP (P = Parameter, M = Member) which avoids to resolve the defaultInstance by using a context bound on the type parameter.
Is there an equivalent way to do this with type members?
EDIT: I have an error in my simplification, actually the foo is not a def but a val, so it is not possible to add an implicit parameter. So no of the current answers are applicable.
trait FooM {
type A
val foo: String = implicitly[TypeCls[A]].foo
}
// end of external fixed API
class FooP[A:TypeCls] { // with type params, we can use context bound
val foo: String = implicitly[TypeCls[A]].foo
}
The simplest solution in this specific case is have foo itself require an implicit instance of TypeCls[A].
The only downside is that it will be passed on every call to foo as opposed to just when instantiating
FooM. So you'll have to make sure they are in scope on every call to foo. Though as long as the TypeCls instances are in the companion object, you won't have anything special to do.
trait FooM {
type A
def foo(implicit e: TypeCls[A]): String = e.foo
}
UPDATE: In my above answer I managed to miss the fact that FooM cannot be modified. In addition the latest edit to the question mentions that FooM.foo is actually a val and not a def.
Well the bad news is that the API you're using is simply broken. There is no way FooM.foo wille ever return anything useful (it will always resolve TypeCls[A] to TypeCls.defaultInstance regardless of the actual value of A). The only way out is to override foo in a derived class where the actual value of A is known, in order to be able to use the proper instance of TypeCls. Fortunately, this idea can be combined with your original workaround of using a class with a context bound (FooP in your case):
class FooMEx[T:TypeCls] extends FooM {
type A = T
override val foo: String = implicitly[TypeCls[A]].foo
}
Now instead of having your classes extend FooM directly, have them extend FooMEx:
class MyFoo extends FooMEx[Int]
The only difference between FooMEx and your original FooP class is that FooMEx does extend FooM, so MyFoo is a proper instance of FooM and can thus be used with the fixed API.
Can you copy the code from the third party library. Overriding the method does the trick.
class MyFooM extends FooM { type A = Int
override def foo: String = implicitly[TypeCls[A]].foo}
It is a hack, but I doubt there is anything better.
I do not know why this works the way it does. It must be some order in which the type alias are substituted in the implicitly expression.
Only an expert in the language specification can tell you the exact reason.

Checking derived class arguments in Scala

Assume the following pair of classes:
class A(arg:String)
class B(argList:Vector[String]) extends A(argList.first)
I want to be able to check for argList being empty before providing the base class constructor with its first element. Unfortunately, placing that check in the default constructor for B (e.g through require, as shown here) is way too late, since the base class' constructor will need to be called first.
This is probably a more general OOP question, but the solution is likely to be Scala-specific.
What do you expect to pass if argList is empty? In any case, you could just use the following:
class B(argList:Vector[String]) extends A(argList.headOption.getOrElse("your default string here")
One way to deal with this is via a companion object. You can mark the constructor for B as private to ensure no-one can by-pass the check, then add a suitable apply method to the companion object that pre-checks the input value(s):
class A(arg:String)
class B private(argList:Vector[String]) extends A(argList.head)
object B {
def apply(argList:Vector[String]): B = argList.headOption.map(_ => new B(argList)).getOrElse(throw new RuntimeException("Oops"))
}
Usage examples:
scala> B(Vector("foo", "bar"))
res2: B = B#328e9109
scala> B(Vector())
java.lang.RuntimeException: Oops
at B$$anonfun$apply$2.apply(<console>:24)
...
Note that for simplicity's sake, I simply throw an exception when handling bad data, but would probably try some other way of handling this situation (a default value per #Zoltan's answer is one such way).
That's why in most places constructors are replaced by factory objects. In Scala it's idiomatic to use companion object as such factories.
class A(arg: String)
abstract class B(arg: String) extends A(arg) {
def argList: IndexedSeq[String]
}
object B {
case object Empty extends B("") {
def argList = IndexedSeq.empty
}
case class NonEmpty private[B](argList: Vector[String]) extends B(argList.head)
def apply(argList: Vector[String]) =
if (argList.isEmpty) Empty else NonEmpty(argList)
def unapplySeq(b:B): Option[IndexedSeq[String]] = b match {
case Empty ⇒ Some(IndexedSeq.empty)
case NonEmpty(args) ⇒ Some(args)
}
}
you could verify that
B(Vector()) == B.Empty
B(Vector("x", "y")).isInstanceOf[B.NonEmpty]

Reify name of class implementing trait as String, from the trait itself

I have a trait that's implemented by a large number of classes, and I'd like to use the names of the classes that implement this trait at runtime, but with as much code centralized as possible.
Specifically, in my code, I'm using tokens to represent classes to be initialized at runtime. The tokens carry configuration, and the actual class is instantiated as needed via the token, combined with run-time information. For linking with resources outside of my app, I want to be able to access the name of the class for which a token is defined. See the example:
trait Token[Cls] {
val className = ???
// Example generic method depending on final class name
def printClassName = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
So, I'm trying to implement className. Ideally, I can pull this information once at compile time. How can I do this, while keeping boilerplate code out of ClassA? Although, if I can drop the type parameter and get the name of the class implementing the Token trait at runtime, that's great too.
Due to Type Erasure Cls is not available on runtime anymore. To get the informations at runtime, you need to use a TypeTag (in your case a ClassTag).
Your code could look like this:
import scala.reflect._
trait Token[Cls] {
def className(implicit ct: ClassTag[Cls]) = ct.runtimeClass.getName
// Example generic method depending on final class name
def printClassName(implicit ct: ClassTag[Cls]) = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
or if it is possible for you to let Token be an class, you could use the ClassTag context bounds:
import scala.reflect._
class Token[Cls: ClassTag] {
def className = classTag[Cls].runtimeClass.getName
// Example generic method depending on final class name
def printClassName = println(className)
}
case class ClassA(t: ClassAToken, runtimeContext: String) {
// a bunch of other code
}
object ClassA {
case class ClassAToken(configParam: String) extends Token[ClassA]
}
For more informations on TypeTags/ClassTags see Scala: What is a TypeTag and how do I use it?

types as mold to delegated classes in Scala

I am working in ScalaFX Project. In this moment I am adapting classes from javafx.scene.control.cell. In this package, methods with same signature are duplicated in many classes. e.g. StringConverter<T> converter(). To avoid unnecessary duplication of code (and to know how to use existential types), I created the following code:
// Defined in scalafx.util package. All classes in scalafx use this trait
package scalafx.util
trait SFXDelegate[+D <: Object] extends AnyRef {
def delegate: D
override def toString = "[SFX]" + delegate.toString
override def equals(ref: Any): Boolean = {
ref match {
case sfxd: SFXDelegate[_] => delegate.equals(sfxd.delegate)
case _ => delegate.equals(ref)
}
}
override def hashCode = delegate.hashCode
}
// Package Object
package scalafx.scene.control
import javafx.{ util => jfxu }
import javafx.beans.{ property => jfxbp }
import javafx.scene.{ control => jfxsc }
import scalafx.Includes._
import scalafx.beans.property.ObjectProperty
import scalafx.util.SFXDelegate
import scalafx.util.StringConverter
package object cell {
type Convertable[T] = {
def converterProperty: jfxbp.ObjectProperty[jfxu.StringConverter[T]]
}
type JfxConvertableCell[T] = jfxsc.Cell[T] with Convertable[T]
trait ConvertableCell[C <: JfxConvertableCell[T], T]
extends SFXDelegate[C] {
def converter: ObjectProperty[StringConverter[T]] = ObjectProperty(delegate.converterProperty.getValue)
def converter_=(v: StringConverter[T]) {
converter() = v
}
}
}
In JfxConvertableCell type I wanna say
My type is a javafx.scene.control.Cell of type T that has a method called converterProperty that returns a javafx.beans.property.ObjectProperty of type javafx.util.StringConverter[T].
While in ConvertableCell trait, my intention is say that delegate value (from SFXDelegate trait) must be of type JfxConvertableCell. The first class that I tried to create was the counter-part of CheckBoxListCell:
package scalafx.scene.control.cell
import javafx.scene.control.{cell => jfxscc}
import scalafx.scene.control.ListCell
import scalafx.util.SFXDelegate
class CheckBoxListCell[T](override val delegate: jfxscc.CheckBoxListCell[T] = new jfxscc.CheckBoxListCell[T])
extends ListCell[T](delegate)
with ConvertableCell[jfxscc.CheckBoxListCell[T], T]
with SFXDelegate[jfxscc.CheckBoxListCell[T]] {
}
However in this moment I got this message from compiler:
type arguments [javafx.scene.control.cell.CheckBoxListCell[T],T] do not conform to trait ConvertableCell's type parameter bounds [C <: scalafx.scene.control.cell.package.JfxConvertableCell[T],T]
Did I understand something wrong? CheckBoxListCell have the converterProperty method. Can't we use types and existential types as a mold into which we fit our delegated classes?
The problem is in your definition of converterProperty. You define it as a parameterless method, while it is seen by scala as a method with an empty parameter list.
Just doing this makes it compile properly:
type Convertable[T] = {
def converterProperty(): jfxbp.ObjectProperty[jfxu.StringConverter[T]]
}
While scala treats a parameterless method and a method with an empty parameter list as essentially the same thing as far as overriding is concerned (see scala spec # 5.1.4), they are still different entites.
And when interroperating with java code (which has no notion of parameterless method), a nullary method is seen as a method with an empty prameter list, not as a parameterless method, thus the structural types don't match.