Inheritance : override in class constructor - scala

I am reading the example in this link http://www.tutorialspoint.com/scala/scala_classes_objects.htm
Example :
class Point(val xc: Int, val yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
println ("Point x location : " + x);
println ("Point y location : " + y);
}
}
class Location(override val xc: Int, override val yc: Int,
val zc :Int) extends Point(xc, yc){
var z: Int = zc
def move(dx: Int, dy: Int, dz: Int) {
x = x + dx
y = y + dy
z = z + dz
println ("Point x location : " + x);
println ("Point y location : " + y);
println ("Point z location : " + z);
}
}
object Test {
def main(args: Array[String]) {
val loc = new Location(10, 20, 15);
// Move to a new location
loc.move(10, 10, 5);
}
}
I didn't understand the utility of override keyword in class location constructor !
Why it is mentioned since we have an extends here ?
Thanks !

Given
scala> class A(val a: Int)
defined class A
If you try to define B like this:
scala> class B(val a: Int) extends A(a)
<console>:11: error: overriding value a in class A of type Int;
value a needs `override' modifier
class B(val a: Int) extends A(a)
compiler complains because it looks like you are trying to define a member a in class B and it already exists there through inheritance (from A). You need to add override to be explicit about your intentions in this case:
scala> class B(override val a: Int) extends A(a)
defined class B
More specifically you don't have to provide an override if you are overriding abstract members:
scala> trait A { def a: Int }
defined trait A
scala> class B(override val a: Int) extends A
defined class B
scala> class B(val a: Int) extends A
defined class B
However, to avoid unintended overrides when mixing in traits Scala protects you by requiring explicit override.
Consider this example:
No problem here:
scala> trait A { def a: Int = 1 }
defined trait A
scala> class B
defined class B
scala> new B with A
res0: B with A = $anon$1#3e29739a
You are saved from ambiguity:
scala> trait A { def a: Int = 1 }
defined trait A
scala> class B { def a: Int = 2 }
defined class B
scala> new B with A
<console>:13: error: <$anon: B with A> inherits conflicting members:
method a in class B of type => Int and
method a in trait A of type => Int
(Note: this can be resolved by declaring an override in <$anon: B with A>.)
new B with A
^
Resolve the conflict manually:
scala> trait A { def a: Int = 1 }
defined trait A
scala> class B { def a: Int = 2 }
defined class B
scala> new B with A { override val a = super[B].a }
res6: B with A{val a: Int} = $anon$1#76f6896b

Related

Scala: using value field to implement a trait method

I tried to do something like this in Scala
trait A {
def foo(i: Int): Int
}
class B(val foo: Int => Int = _ + 1) extends A
But somewhat surprisingly I got this error from the compiler:
error: class B needs to be abstract, since method foo in trait A of type (i: Int)Int is not defined
class B(val foo: Int => Int = _ + 1) extends A
And this didn't work either with the same error:
class C extends A {
val foo: Int => Int = _ + 1
}
However this (obviously) worked:
class D(val bar: Int => Int = _ + 1) extends A {
def foo(i: Int): Int = bar(i)
}
scala> (new D).foo(5)
res1: Int = 6
So the question is, why is Scala treating def foo(i: Int): Int = ... differently than val foo: Int => Int = ...
Because, def foo(i: Int): Int defined in the trait: is a function which takes an integer as input and returns an integer as the output.
Where as, val foo: Int => Int = _ + 1 defined in the class: is a function, which returns a function. That's the key point, you have not implemented the one from trait. The foo in the class B is returning a function and the returned function takes an integer as input and provided an integer in the output.
Finally, I found an embarrassingly simple solution to my problem. All I had to do was to change my trait into this:
trait A { def foo: Int => Int }
And now it works as desired:
class B(val foo: Int => Int = _ + 1) extends A
scala> (new B).foo(6)
res3: Int = 7

Why implicit conversion is not applied to second argument?

When I try to compile the following code
case class A(x: Int = 0)
object Conversions {
case class Converter[T](c: T) {
def +[U](that: Converter[U]): String = "worked"
}
implicit def convert(c: A): Converter[A] = Converter[A](c)
implicit def convert(c: Int): Converter[Int] = Converter[Int](c)
}
object Main extends App {
import Conversions._
val a: String = A() + A()
val b: String = 1 + A() // FAIL
val c: String = A() + 1
val d: Int = 1 + 1
}
I get the following error message
error: type mismatch; found: A; required: String
What is the difference between Int and A, so that expression b fails, while a and c pass? What do I do to make it compile?
First, the difference is that Int already has another + method, which expects another Int and returns an Int;
If you add a similar method to A you'd get similar failures:
case class A(x: Int = 0) {
// this would be similar to Int's plus operation:
def +(other: A): A = A(x + other.x)
}
// now these would behave "symmetrically":
val a: A = A() + A()
val b: String = 1 + A() // FAIL
val c: String = A() + 1 // FAIL
val d: Int = 1 + 1
As for why that fact causes this specific failure - that's trickier, I assume it has to do with the order in which the compiler tries to "choose" the right implicit conversion based on the left and right argument.
If you replace the arithmetic + operator with, say plus:
def plus[U](that: Converter[U]): String = "worked"
your implicit conversions should work the way you expect:
val a = A() plus A() // worked
val b = 1 plus A() // worked
val c = A() plus 1 // worked
val d = 1 plus 1 // worked
Rather than a direct implicit conversion between Int and A, your implicit conversions are between Int and class Converter (and, between A and Converter). The compiler apparently is having a hard time sorting through the conversion rules between Int and A when it sees a + method well defined for Int – unless you provide a direct implicit conversion between Int and A like in the following example:
object A {
implicit def intToA(n: Int): A = A(n)
}
case class A(x: Int = 0) {
def +(that: A): A = A(this.x + that.x)
}
val a = A(1) + A(2) // A(3)
val b = 1 + A(1) // A(2)
val c = A() + 1 // A(1)
val d = 1 + 1 // 2
I have no clear understanding on why this attempt was successful, but I hope that it will be useful to other users. Here I'm matching on both arguments at the same time to minimize Scala's attempts to bruteforce correct tree of implicit conversions.
object Defs {
case class A(x: Int = 1)
case class B(x: Int = 2)
trait IsExpr[T] {
def conv(v: T): Int
}
implicit object aIsExpr extends IsExpr[A] {
override def conv(v: A): Int = v.x
}
implicit object bIsExpr extends IsExpr[B] {
override def conv(v: B): Int = v.x
}
implicit def canSum1[A, B](a: A, b: B)(implicit ca: IsExpr[A], cb: IsExpr[B]): Int = ca.conv(a) + cb.conv(b)
implicit def canSum2[A](a: A, b: Int)(implicit ca: IsExpr[A]): Int = ca.conv(a) + b
implicit def canSum3[A](a: Int, b: A)(implicit ca: IsExpr[A]): Int = a + ca.conv(b)
implicit def convert[A](a: A) = new {
def +[B](b: B)(implicit f: (A, B) => Int): Int = f(a, b)
}
}
object Main extends App {
import Defs._
val a: Int = A() + A()
val b: Int = 1 + A()
val c: Int = A() + 1
val d: Int = 1 + 1
}

Infer a return type of a method based on the type expected in call site?

So, basically, what I want to do is:
object WithoutWrap {
def f[T: ClassTag](x: String): T = {
println("Class of T is really… " ++ implicitly[ClassTag[T]].toString)
??? : T
}
def y: Int = f("abc")
def z: Int = f[Int]("abc")
}
In both cases I’d like the inferred T to be Int. Let’s run this:
scala> WithoutWrap.y
Class of T is really… Nothing
scala.NotImplementedError: an implementation is missing
scala> WithoutWrap.z
Class of T is really… Int
scala.NotImplementedError: an implementation is missing
Unfortunately it’s Nothing in the first case.
However, if we return the T wrapped in something,
object WithWrap {
trait Wrap[T]
def f[T: ClassTag](x: String): Wrap[T] = {
println("Class of T is really… " ++ implicitly[ClassTag[T]].toString)
??? : Wrap[T]
}
def y: Wrap[Int] = f("abc")
def z: Wrap[Int] = f[Int]("abc")
}
… the T is inferred correctly in both cases:
scala> WithWrap.y
Class of T is really… Int
scala.NotImplementedError: an implementation is missing
scala> WithWrap.z
Class of T is really… Int
scala.NotImplementedError: an implementation is missing
How to get Int in both cases without wrapping?
Depending on what you're trying to accomplish, overload resolution is sensitive to expected type:
scala> case class A(s: String) ; case class B(s: String)
defined class A
defined class B
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X {
def f(s: String): A = A(s)
def f(s: String)(implicit d: DummyImplicit): B = B(s)
}
// Exiting paste mode, now interpreting.
defined object X
scala> val x: A = X f "hi"
x: A = A(hi)
scala> val y: B = X f "hi"
y: B = B(hi)

How can I remove this extra type parameter?

I currently have:
class X[+T: Numeric](val x: T)
abstract class M[N: Numeric, T <: X[N]] { // <- I'd like to remove N.
def apply(x: Int): T
final def row = (1 to 10).map(this(_))
}
I use it like this:
class Y(x: Double, val y: Double) extends X[Double](x)
class Z extends M[Double, Y] { // <- So that this is simpler.
def apply(x: Int) = new Y(0.0, 0.0)
}
It works like this:
object testapp {
// row is properly polymorphic, allowing access to Y.y
def main(args: Array[String]): Unit = (new Z).row.map(r => println(r.y))
}
I want Z to be simpler so that I can use M like:
class Z extends M[Y] {
def apply(x: Int) = new Y(0.0, 0.0)
}
or, even better:
class Z extends M[Double] { // i.e. Meaning apply can return
def apply(x: Int) = new Y(0.0, 0.0) // any subclass of X[Double]
}
Here are my Gist iterations to reach this point.
A third way in type params vs type members is to use both.
An advantage of a type member is that it doesn't pollute the signature of child classes. The type member can remain abstract if it is superfluous (even in a concrete class); and only the bottom class must define it if necessary.
import scala.collection.immutable.IndexedSeq
class X[+T: Numeric](val x: T)
abstract class M[+A: Numeric] {
type W <: X[A]
def apply(x: Int): W
final def row: IndexedSeq[W] = (1 to 10) map apply
def sumx: A = { // in terms of the underlying Numeric
val n = implicitly[Numeric[A]]
n fromInt (0 /: row)((s,w) => s + (n toInt w.x))
}
}
class Y(x: Double, val y: Double) extends X[Double](x)
class Z extends M[Double] {
type W = Y
def apply(x: Int) = new Y(0.0, 0.0)
}
def main(args: Array[String]): Unit = (new Z).row foreach (Console println _.y)
You didn't really need class M here:
class X[+T: Numeric](val x: T)
def row[W <: X[_]](c: => Int => W) = (1 to 10).map(c)
class Y(x: Double, val y: Double) extends X[Double](x)
def z = row(_ => new Y(0.0, 0.0))
def main(args: Array[String]): Unit = z.map(r => println(r.y))
If you want to keep M, you use same idea:
class X[+T: Numeric](val x: T)
abstract class M[W <: X[_]] {
def apply(x: Int): W
final def row = (1 to 10).map(this(_))
}
class Y(x: Double, val y: Double) extends X[Double](x)
class Z extends M[Y] {
def apply(x: Int) = new Y(0.0, 0.0)
}
def main(args: Array[String]): Unit = (new Z).row.map(r => println(r.y))

Why is this Scala example of implicit parameter not working?

simple REPL test...
def g(a:Int)(implicit b:Int) = {a+b}
Why do neither of these attempted usages work?
1.
scala> class A { var b:Int =8; var c = g(2) }
:6: error: could not find implicit value for parameter b: Int
class A { var b:Int =8; var c = g(2) }
2.
scala> class A(var b:Int) { var c = g(2) }
:6: error: could not find implicit value for parameter b: Int
class A(var b:Int) { var c = g(2) }
^
Thanks
you need to define b as implicit in A
scala> def g(a:Int)(implicit b:Int) = {a+b}
g: (a: Int)(implicit b: Int)Int
scala> class A { implicit var b:Int =8; var c = g(2) }
defined class A
scala> val a = new A
a: A = A#1f7dbd8
scala> a.c
res3: Int = 10
In general, only values/methods that are defined as implicits will be considered and they are searched in scope, or in the companion object of the required type (Int in this case)
You have to specify which var or val will be used as the implicit value:
scala> def g(a:Int)(implicit b:Int) = {a+b}
g: (a: Int)(implicit b: Int)Int
scala> class A { implicit var b:Int =8; var c = g(2) }
defined class A
scala> new A
res0: A = A#16b18b6
scala> res0.c
res1: Int = 10
scala> class A(implicit var b:Int) { var c = g(2) }
defined class A