Can't understand path dependent type - scala

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.

Related

Access field from trait in companion object

I have something like the following code (I simplified it):
trait A {
val CONST_VALUE = 10
}
class B(someValue: Int, values: Array[Int]) extends A {
//some methods
}
object B {
def apply(someValue: Int) = B(someValue, Array.ofDim[Array[Byte]](someValue).map(block => Array.fill[Byte](A.CONST_VALUE)(0)))
}
Basically, I declared a constant CONST_VALUE in the trait A. I am trying to use it in the companion object B to instantiate the class B. However, I can't access A.CONST_VALUE from the companion object B.(I'm getting a compilation error).
So how could I do this?
You can't do this.
First of all, object B is the companion object to class B, not to trait A. Companions need to have the same name and be defined in the same compilation unit.
Secondly, CONST_VALUE is an instance field of trait A. It is a member of an instance of A, not a member of A.
Thirdly, when you say A.CONST_VALUE you are basically calling the method CONST_VALUE on A. But you can only call methods on objects/values. A is not an object, it is a type, types and values live in different worlds, you cannot mix the two.
And fourth, your CONSTANT_VALUE is misleadingly named: only final vals are constant value definitions, so your CONSTANT_VALUE is not actually a constant value.
Fifth, your apply method calls itself (B() is syntactic sugar for B.apply()), and thus needs a return type annotation.
Sixth, your apply method calls itself with two arguments, but it is defined with only one parameter.
Seventh, you create an Array[Array[Byte]], but it is not clear to me why you want to do that and what you need it for.
That's a whole truckload of problems (especially considering that there are only a handful of lines of code to begin with), which you need to fix one-by-one. Here's one possible partial solution, but it is not clear to me what it is exactly that you are trying to achieve.
trait A
object A {
final val CONST_VALUE = 10
}
class B(someValue: Int, values: Array[Int]) extends A {
//some methods
}
object B {
def apply(someValue: Int): B = new B(
someValue,
Array.ofDim[Array[Byte]](someValue).map(block => Array.fill[Byte](A.CONST_VALUE)(0)))
}
Declare val CONST_VALUE = 10 inside the companion object A instead of trait A. Also corrected the apply method definition in object B
trait A {
}
object A {
final val CONST_VALUE = 10
}
class B(someValue: Int, values: Array[Int]) extends A {
//some methods
}
object B {
def apply(someValue: Int) = new B(someValue, Array.ofDim[Int](someValue).flatMap(block => Array.fill[Int](A.CONST_VALUE)(0)))
}

Accessing to methods of case classes

Why I can't access to methods of case class inside method of ordinary class when I initiate case class instance without new keyword?
I.e. in the following code I get a compile-time error:
case class A() {
private var _g = 12
//getter-setter
def g = _g
def g_=(value : Int) = this._g = value
}
class B {
def someMethod = {
val aInstance = A
aInstance.g = 4; // compile time error. Why?
}
}
But if I add new keyword in aInstance declaration all work fine.
Error message is:
Cannot resolve symbol g
You need to make an instance of class A with A() (which calls apply on A). Otherwise you're referring to the companion object itself.
How about this? You did not define f and meant probably aInstance.
class B {
def someMethod = {
val aInstance = A
aInstance.g = 4
}
}

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

Can a scala class be instantiated in same way as java

Below class does not compile, if I declare Functions as an object instead of class I can run the method fac using Functions.fac(3) . Does it make sense in scala to attempt to run a class like this ? How can the below code be modified so that it runs without changing to object instead of class ?
class Functions {
def fac(n : Int) = {
var r = 1;
for(i <- 1 to n) r = r * i;
r
}
def main(args:Array[String]) = {
Functions f = new Functions();
print(f.fac(3));
}
}
The most obvious problem in your code is that you have Functions f = .... This is Java syntax, so in Scala you need it to say val f: Functions = ...
Second, Scala makes a larger distinction between static and non-static things than Java. In Scala, something that's static (such as a main method) is declared in an object. So you should separate the object (static) parts from the class parts.
Third, your fac function could be more simply written as (1 to n).product.
Finally, you don't need the semi-colons.
class Functions {
def fac(n: Int) =
(1 to n).product
}
object Functions {
def main(args: Array[String]) = {
val f: Functions = new Functions()
print(f.fac(3))
}
}
Java and Scala implement static functions very differently. In Java you add the static identifier, while in Scala you put the method in the Object companion.

How to start the object

i need help with this code.
object test {
var list : Vector[MyType] = null
}
object foo extends MyType { // Mytype is a trait
println("TEST ")
test.list.:+(foo)
def myfunc() { //need to define this as this is there in the trait
// i do some operations
}
}
object Bar extends MyType { // Mytype is a trait
println("TEST ")
test.list.:+(Bar)
def myfunc(){
// i do some operations
}
}
now i want to go through the list and call myfunc() for all the objects that are extending MyType.
test.list foreach( t2 => t2.myfunc() )
the value's are not getting added to the list. Can someone let me know what i am doing wrong. Its not working. Is there a way to get that print statement working?
Your problem is, that the object is not constructed as a class, so that the code is called automatically. You could do two things. Either you extend App and call main or you write a function.
trait X
object test {
var list = Vector.empty[X]
}
object Foo extends App with X {
test.list :+= Foo
override def toString() = "Foo"
}
object Bar extends X {
def add() {
test.list :+= Bar
}
override def toString() = "Bar"
}
Foo.main(null)
Bar.add()
test.list foreach println
This code prints:
Foo
Bar
Extending App only adds a main methode to an object, containing all the code in the object.
You need to initialize test with an empty Vector rather than null. The way to do that in Scala is to use the factory method from the Vector object, and let type-inference do its job. For example:
var list = Vector.empty[MyType]
As you get the practice of doing that, you'll find yourself more focused on creating the data than on declaring its type, which in this case would have resolve this error before it happened.
Next the operation
test.list.:+(foo)
will not update test.list because, since Vector is immmutable, this method just returns a new updated copy and cannot affect the reference of list.
Try instead
test.list = test.list.:+(foo)
// or (with more idiomatic operator notation)
test.list = test.list :+ foo
// or (using syntactic sugar)
test.list :+= foo