How to understand `C.super[P]` in scala? - scala

I'm reading the book of "The depth of scala", and on chapter 6 "types", page 123:
The path C.super or C.super[P] where C refers to a class and P refers to a par- ent type of class C. Using the super keyword directly is shorthand for C.super. Use this path to disambiguate between identifiers defined on a class and a par- ent class.
I can't understand the C.super[P], why we can specify the type P after super?
I tried this scala code:
class P {
def hello = "hello from P"
}
class C extends P {
override def hello = "hello from C"
}
class D extends C {
override def hello = super[P].hello
}
val d = new D
d.hello
Which is unable to compile on this line:
override def hello = super[P].hello

Note that P must be a parent type, not any supertype. I.e. if you have class D extends C with T1 with T2, and there is a hello method in class C and traits T1 and T2, just writing super.hello wouldn't tell the compiler which hello method you want. So you can write super[C].hello, super[T1].hello or super[T2].hello.

Related

scala use template type to resolve sub class

I am fairly new to Scala and trying to do some code reuse. I have two enums AB and AC, both extend A which is a trait with some common methods.
object AB extends A[AB]{
val X = Value("x")
}
object AC extends A[AC]{
val Y = Value("y")
}
trait A[T] extends Enumeration{
def getProperty(prop: T.Value): String = {
//some code that uses prop.toString
}
I am trying to have a getProperty method that will restrict users to only Enums from the enumeration that it is being called upon.
if I call AB.getProperty() than i should be able to pass only X. if I call AC.getProperty than I should be able to pass only Y
If I have to redesign my classes that is fine. Please let me know how I can achieve this.
Thanks in advance
I am not sure what ConfigProperties is in your code, and why you need the type parameters, but the answer to your question is, declare the parameter type in geProperty as Value -> getProperty(prop: Value).
Value is a nested abstract class in Enumeration, so it will be expanded by the compiler respectively to AB.Value and XY.Value, depending on the instance. A simplified example which you can test in the REPL:
object AB extends A {
val A = Value('A')
val B = Value('B')
}
object XY extends A {
val X = Value('X')
val Y = Value('Y')
}
trait A extends Enumeration {
def getProperty(prop: Value): String = {
//some code that uses prop.toString
prop.toString()
}
}
AB.getProperty(AB.A) // OK
XY.getProperty(XY.Y) // Also OK
// AB.getProperty(XY.X) <- this won't compile
// Error:(21, 20) type mismatch;
// found : A$A238.this.XY.Value
// required: A$A238.this.AB.Value
// AB.getProperty(XY.X)
//

Can't understand path dependent type

For a class C, you can use the familiar this inside the body to refer to the current instance, but this is actually a shorthand for C.this in Scala:
class C {
var x = "1"
def setX1(x:String) = this.x = x
def setX2(x:String) = C.this.x = x
}
I just can't understand C.this, C is a class, I can't understand why we use dot between C and this as shown in C.this?
I can't understand why we use dot between C and this as shown in
C.this
Using the class name before this is called a Qualified this in Java (see Using "this" with class name) and is similar in Scala. You use it when you want to reference an outer class from an inner class. Let's assume for example that you had a method declaration in your C class where you wanted to call this and mean "the this reference of C:
class C {
val func = new Function0[Unit] {
override def apply(): Unit = println(this.getClass)
}
}
new C().func()
Yields:
class A$A150$A$A150$C$$anon$1
You see the anon$1 at the end of the getClass name? It's because inside the function instance this this is actually of the function class. But, we actually wanted to reference the this type of C instead. For that, you do:
class C {
val func = new Function0[Unit] {
override def apply(): Unit = println(C.this.getClass)
}
}
new C().func()
Yields:
class A$A152$A$A152$C
Notice the C at the end instead of anon$1.

Scala - choose a method of one trait over another

I am new to scala. I was learning traits and it seems that they can have concrete methods. Here is the code I have written.
trait A{
def print : Unit = {
println("I am in A")
}
}
trait B{
def print : Unit = {
println("I am in B")
}
}
trait C {
def print : Unit = {
println("I am in C")
}
}
class D extends A with B with C{
}
object Main extends App {
val d: D = new D
d.print
}
It is giving a compilation error obviously. The compiler is asking me to override the print method in D. I don't want to write a new method. I just want to choose C's print method over others. Is there any way I can choose only C's print method? I hope I have made myself clear. I am sorry if the question sounds stupid. I am trying to learn. Thanks in advance.
#S.K, so the last trait I mix in is the super class?
If you look at the documention of Scala trait, whenever scala compiler see any class with multiple parent scala compiler will place all the classes in stackable form.
so If A extends B with C will become --> A->B->C and when you invoke super from you base class A it will consider method like C->B (C then B).
same way if you make A extends C with B will become --> A->C->B and when you invoke it compiler will consider B->C (B then C).
Please see more detials on scala trait stackable at below link.
Scala's Stackable Trait Pattern
I am agree with S.K what is a problem to override in class D.
One way you are extending your D class with C and without overriding how can you get the handle of method in C?
You have to override in order to call it's method.

In Scala, member of a class is not found when its instance is accessed from a list [Class]

I have a feeling that the problem I am facing has something to do with Type Erasure of Scala, but as a newbie I can't put my fingers on it. Need some help here.
First, the code:
class C (val i: Int) {
def mkString() = { println("C.i =" + this.i) }
object C {
implicit val cOrdering = new Ordering [C]
{
def compare (a: C, b: C)=
{
a.i compare b.i;
}
}
Then, I create another class which holds a collection of class 'C' thus:
class ContainerOfC [C] (s:Int) (implicit ordering: cOrdering[C]) {
var internalCollection = new TreeSet[C]()
def + (c:C): ContainerOfC [C] = {
this.internalCollection += c
this
}
def mkStringOfElems () = {
val y = this.internalCollection.toList
println (y.head.i) // <--- Problem here
}
}
This is what REPL tells me:
error: value i is not a member of type parameter C
println(y.head.i)
^
I have checked the type of 'y' out there: it is a List[C]. If so, why am I not allowed to access the 'i'? It is a construction parameter alright, but it is a val and hence, can be treated as a member variable, can't it be?
I have gone through a few of the other related posts in the forum, and Manifests and Typetags are possible ways out here. But, I am not sure if I need to go to that level for this simple use-case.
This have a strange and familiar feeling of "been there, done that".
How about you try to change this:
class ContainerOfC [C] (s:Int) (implicit ordering: cOrdering[C]) { ... }
to this without the type parameter C in the declaration :
class ContainerOfC(s:Int) (implicit ordering: cOrdering[C]) { ... }
The code you showed created a class and specific type C. When you later write class ContainerOfC[C], that C is a type parameter that could be named by any other identifier. It is the same as defining class ContainerOfC[A] where A does not have any relation to the class/type C defined in the earlier code. In your example the type parameter C would shadow the name of the class defined earlier... The error message is indicating that C does not have a value i and that's because the compiler is not referring to the same C than you are thinking of.
Edit: just so you know quickly if we are on the same page without getting bogged down in other compilation errors, here are a few edits to make the code compile and using more commonly used indentation and brace style:
class C(val i: Int) {
def mkString() = println("C.i =" + this.i)
}
object C {
implicit val cOrdering = new Ordering[C] {
def compare(a: C, b: C) = a.i compare b.i
}
}
class ContainerOfC(s: Int)(implicit ordering: Ordering[C]) {
var internalCollection = new collection.mutable.TreeSet[C]()
def +(c: C): ContainerOfC = {
this.internalCollection += c
this
}
def mkStringOfElems() = {
val y = this.internalCollection.toList
println(y.head.i)
}
}

Scala - mixing in a trait with its imports (inheriting imports)

I have the following code:
trait A {
import org.somepackage.C._
}
class B extends A {
def getValue = value
^^^^^
}
object C {
var value = 5
}
The value in class B is not visible what means that the inherent import of class A was not inherited by B, although the value is perfectly visible inside A. How to achieve the effect of also inheriting imports so I could avoid explicitly importing same things in multiple classes where trait A mixes in?
Imports not being a first class entity do not exhibit the behavior you are expecting. You can instead restructure your design thusly to achieve something close:
trait A with C {
}
class B extends A {
def getValue = value // Now this will work.
}
trait C {
var value = 5
}
object C extends C
This idiom is used in Scalaz 6 to tax users with as few imports as possible.