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
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)
}
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))
}
}
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)
}
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))
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)
???
}
}