Scala constructor signature - scala

Is it possible to define constructor signature in Scala ?
abstract class A {
def this (s: String): this.type // doesn't work
def this (i: Int): this.type // doesn't work
def this (d: Double): this.type // doesn't work
}
class B(var s: String) extends A {
def this(i: Int) = {
this("int "+i.toString())
}
def this(d: Double) = {
this("double "+d.toString())
}
}

What are you trying to achieve? You can do like this:
abstract class A(i: Int)
case class B(s: String) extends A(s.toInt) {
def this(i: Int) = {
this(i.toString)
}
def this(d: Double) = {
this(d.toString)
}
}
Usage:
B("1")
new B(1)
new B(1.0)

You can't do exactly what you want, as pointed out by other answer, but one approach is to use a factory:
trait Foo {
// methods you need
}
trait FooCompanion[T <: Foo] {
// these methods replace constructors in your example
def apply(s: String): T
def apply(i: Int): T
...
}
Implementation:
class Bar(s: String) extends Foo {
...
}
object Bar extends FooCompanion[Bar] {
def apply(s: String) = new Bar(s)
...
}
and you can have methods taking FooCompanion. This pattern is used e.g. in the Scala collections library.

No that is not possible. Constructors are special: You need to write new X() instead of X(), and there is no polymorphic dispatch, e.g. you cannot do def test[A]() = new A(). So there is no scenario in which an abstract constructor would make any sense.

Related

Scala implicit class based on type class

implicit class IntIncrement(val underlying: Int) extends AnyVal {
def increment(): Int = underlying + 1
}
This is valid and allows me to do something like 1.increment()
I want to be able to constrain a type parameter to have this .increment() method on it, so I started doing this:
trait Increment[T] {
def increment(value: T): T
}
object Increment {
implicit val implInt: Increment[Int] = new Increment[Int] {
def increment(value: Int): Int = {
value + 1
}
}
}
def increment[T](value: T)(implicit valueIntDec: Increment[T]): T = {
valueIntDec.increment(value)
}
issue is, this increment method only allows for increment(1) instead of 1.increment()
is there any way to create an implicit class for any T that has an implicit of Increment[T]
implicit class ImplicitIncrement[T](val underlying: implicit Increment[T]) extends AnyVal {
def increment(): T = increment(underlying)
}
something like this ^^
You can do that, just without AnyVal:
implicit class TIncrement[T : Increment](val underlying: T) {
def increment: T = implicitly[Increment[T]].increment(underlying)
}
But I am not sure I see the value in delegating to the type class here: rather than creating a type class implementation for every "incrementable" type, why not just have separate implicit classes that would just increment directly?
like
implicit class I(val v: Int) extends AnyVal { def increment = v + 1 }
implicit class L(val v: Long) extends AnyVal { def increment = v + 1 }
// etc
UPDATE
Actually, you can do that with type class and AnyVal too:
implicit class TIncrement[T](val underlying: T) extends AnyVal {
def increment(implicit inc: Increment[T]): T = inc.increment(underlying)
}

How to make method return type covariant

I have a following classes:
trait Foo {
def update: Foo
}
class ConcreteFoo extends Foo {
override def update: Foo = new ConcreteFoo
}
class FooManager[T <: Foo](val foos: mutable.Map[String, T]) {
def update(id: String): Unit = {
foos.update(id, foos(id).update)
}
}
And of course update function does not compiles:
Type missmatch found Foo required T
How to make def update: Foo covariant?
Looks like you want something like F-bounded polymorphism:
trait Foo[T <: Foo[T]] { self: T =>
def update: T
}
class ConcreteFoo extends Foo[ConcreteFoo] {
override def update = new ConcreteFoo
}
class FooManager[T <: Foo[T]](val foos: mutable.Map[String, T]) {
def update(id: String): Unit = {
foos.update(id, foos(id).update)
}
}
An alternative, and probably simpler, solution is to use an immutable Map, as Luka said. But then there's no need to have type parameters anymore:
trait Foo {
def update: Foo
}
class ConcreteFoo extends Foo {
override def update: Foo = new ConcreteFoo
}
class FooManager(private var _foos: immutable.Map[String, Foo]) {
def foos = _foos
def update(id: String): Unit = {
_foos = _foos.updated(id, _foos(id).update)
}
}
You could also keep your current solution and remove the type parameter. But then you have the slight inconvenience that you can't pass a mutable.Map[String,ConcreteFoo] to the constructor of FooManager.
I'd suggest going with an immutable Map instead. As only immutable collections can have covariant type parameters.
class FooManager[+T <: Foo](val foos: immutable.Map[String, T]) {
def update(id: String): FooManager[Foo] = {
new FooManager(foos.updated(id, foos(id).update))
}
}

Scala tuple unpacking for constructors with abstract class for inheritance

I have a Scala class with two parameters, and another one parameter constructor. For the one parameter constructor, I called a method to get a tuple of two elements and tried to use the tuple for the parameter of the constructor that requires two parameters. From this post: Scala tuple unpacking for constructors I could get an answer for the non-inheritance case, but I need to use the method for inheritance case.
This is my code, but I'm not sure how to instantiate the abstract class.
abstract class A(val a:Int, val b:Int) {
def h()// = ???
}
object A {
def apply(pair: (Int, Int)): A = new A(pair._1, pair._2)
def apply(v: Int): A = A(vals(v))
def vals(v:Int) = {
(v,v)
}
}
class B(override val a:Int, override val b:Int) extends A(a,b) {
override def h() = ???
}
object B {
def apply(pair: (Int, Int)): B = new B(pair._1, pair._2)
def apply(v: Int): B = B(A.vals(v))
}
object Main extends App {
val a = B(10)
println(a.a, a.b)
}
Of course, I got an error message if I tried to instantiate the abstract class.
error: class A is abstract; cannot be instantiated
def apply(pair: (Int, Int)): A = new A(pair._1, pair._2)
^
I think the simplest solution is just make the abstract class non abstract, and giving dummy body def h() = ???. However, I'm not sure there might be better way.
From Shadowlands' hint, I could just use the apply() only for concrete classes.
// http://stackoverflow.com/questions/32512401/scala-tuple-unpacking-for-constructors
abstract class A(val a:Int, val b:Int) {
def h()// = ???
}
object A {
def vals(v:Int) = {
(v,v)
}
}
class B(override val a:Int, override val b:Int) extends A(a,b) {
override def h() = ???
}
object B {
def apply(pair: (Int, Int)): B = new B(pair._1, pair._2)
def apply(v: Int): B = B(A.vals(v))
}
object Main extends App {
val a = B(10)
println(a.a, a.b)
}

Scala: Polymorphic daisy chaining

class Foo(protected[this] val s: Iterator[String]) {
def apply(it: Iterator[String]): Foo = new Foo(it ++ s)
}
class Bar(s: Iterator[String]) extends Foo(s) {
}
Question: How can I get Bar.apply() to return a new Bar instead of a new Foo? I don't want to override.
You can use F-bounded polymorphism to get an apply that returns the proper type. You also need to define a method that creates an instance of the subclass:
abstract class Foo[X](protected[this] val s: Iterator[String]) {
self: X =>
def newSubclass(s: Iterator[String]): X
def apply(it: Iterator[String]): X = newSubclass(it ++ s)
}
class Bar(s: Iterator[String]) extends Foo[Bar](s) {
def newSubclass(s: Iterator[String]): Bar = new Bar(s)
}
Bar.apply will have Bar as its return type, without needing to be overriden.
You can read more about F-bounded polymorphism at the Twitter Scala school.
Have looked through this article. Seems it's what you want. Quickly scetch out simple example(using var's in this example)
class A(var s: String) {
def apply(a: String): this.type = {
s = "A" + a
this
}
}
class B(var s: String) extends A(s)
P.S.: Tried to use vals but it is impposible to call constructor in method which return type is this.type. Maybe you'll find the solution))

How to call `apply` on a superclass in Scala?

My class inherits from some base class, and implements apply method with exactly the same signature as the base's one. I want to call base's apply method from my class.
When I try following:
class MyClass extends BaseClass {
def apply(k: String, v: String) = {
super.apply(k, v)
...
}
...
}
I got value apply is not a member of BaseClass... compile error.
How should I call base's apply method from the child class?
Also, why it is possible to override apply method without an override keyword?
EDIT: Actual code:
class OAuthParamsBuilder(helper: OAuthParamsHelper)
extends KeyValueHandler {
def apply(k: String, v: String): Unit = {
...
}
}
class OAuthInitSupportBuilder
extends OAuthParamsBuilder(StandardOAuthParamsHelper) {
/*override*/ def apply(k: String, v: String): Unit = {
super.apply(k, v)
...
}
...
}
EDIT: I've noticed that KeyValueHandler is a trait, this may be an issue.
trait KeyValueHandler extends ((String, String) => Unit)
You are not helping us help you, but I suspect this is the true definition of apply on the base class:
def apply(kv: (String, String)) = ???
EDIT
The code you pasted is not enough, as the problem is not reproducible with it:
trait OAuthParamsHelper
trait KeyValueHandler
class OAuthParamsBuilder(helper: OAuthParamsHelper) extends KeyValueHandler {
def apply(k: String, v: String): Unit = ???
}
object StandardOAuthParamsHelper extends OAuthParamsHelper
class OAuthInitSupportBuilder extends OAuthParamsBuilder(StandardOAuthParamsHelper) {
override def apply(k: String, v: String): Unit = {
super.apply(k, v)
???
}
}