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
}
}
Related
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)
//
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.
I have the following class setup:
class MyClass {
class MyInnerClass(memberVar: String)
def getAInner: MyInnerClass = {
new MyInnerClass("hello")
}
}
Then I have the following code outside of the class:
def myFunction = {
val a = new MyClass
val b = a.getAInner.memberVar // value memberVar is not a member of a.MyInnerClass
}
Why is this?
You need to add the keyword val to make memberVar public otherwise it's a private value:
class MyClass {
class MyInnerClass(val memberVar: String)
def getAInner: MyInnerClass = {
new MyInnerClass("hello")
}
}
#Noah's answer is totally correct, but I would also throw out the option of using case class. See here for some of the sugar it provides. I use it almost reflexively. In your example, it would be:
object MyClass {
case class MyInnerClass(memberVar: String)
def getAInner: MyInnerClass = {
new MyInnerClass("hello")
}
}
def myFunction = {
val b = MyClass.getAInner.memberVar
}
I tend to do it this way because invariably, I want to take advantage of the sane defaults case class provides.
I also chose to use object for the outer type, because it doesn't have any parameters, although you may have just done that for simplicity's sake.
Search results so far have led me to believe this is impossible without either a non-primary constructor
class Foo { // NOT OK: 2 extra lines--doesn't leverage Scala's conciseness
private var _x = 0
def this(x: Int) { this(); _x = x }
def x = _x
}
val f = new Foo(x = 123) // OK: named parameter is 'x'
or sacrificing the name of the parameter in the primary constructor (making calls using named parameters ugly)
class Foo(private var _x: Int) { // OK: concise
def x = _x
}
val f = new Foo(_x = 123) // NOT OK: named parameter should be 'x' not '_x'
ideally, one could do something like this:
class Foo(private var x: Int) { // OK: concise
// make just the getter public
public x
}
val f = new Foo(x = 123) // OK: named parameter is 'x'
I know named parameters are a new thing in the Java world, so it's probably not that important to most, but coming from a language where named parameters are more popular (Python), this issue immediately pops up.
So my question is: is this possible? (probably not), and if not, why is such an (in my opinion) important use case left uncovered by the language design? By that, I mean that the code either has to sacrifice clean naming or concise definitions, which is a hallmark of Scala.
P.S. Consider the case where a public field needs suddenly to be made private, while keeping the getter public, in which case the developer has to change 1 line and add 3 lines to achieve the effect while keeping the interface identical:
class Foo(var x: Int) {} // no boilerplate
->
class Foo { // lots of boilerplate
private var _x: Int = 0
def this(x: Int) { this(); _x = x }
def x = _x
}
Whether this is indeed a design flaw is rather debatable. One would consider that complicating the syntax to allow this particular use case is not worthwhile.
Also, Scala is after all a predominantly functional language, so the presence of vars in your program should not be that frequent, again raising the question if this particular use case needs to be handled in a special way.
However, it seems that a simple solution to your problem would be to use an apply method in the companion object:
class Foo private(private var _x: Int) {
def x = _x
}
object Foo {
def apply(x: Int): Foo = new Foo(x)
}
Usage:
val f = Foo(x = 3)
println(f.x)
LATER EDIT:
Here is a solution similar to what you originally requested, but that changes the naming a bit:
class Foo(initialX: Int) {
private var _x = initialX
def x = _x
}
Usage:
val f = new Foo(initialX = 3)
The concept you are trying to express, which is an object whose state is mutable from within the object and yet immutable from the perspective of other objects ... that would probably be expressed as an Akka actor within the context of an actor system. Outside the context of an actor system, it would seem to be a Java conception of what it means to be an object, transplanted to Scala.
import akka.actor.Actor
class Foo(var x: Int) extends Actor {
import Foo._
def receive = {
case WhatIsX => sender ! x
}
}
object Foo {
object WhatIsX
}
Not sure about earlier versions, but In Scala 3 it can easily be implemented like follows:
// class with no argument constructor
class Foo {
// prive field
private var _x: Int = 0
// public getter
def x: Int = _x
// public setter
def x_=(newValue: Int): Unit =
_x = newValue
//auxiliary constructor
def this(value: Int) =
this()
_x = value
}
Note
Any definition within the primary constructor makes the definition public, unless you prepend it with private modifier
Append _= after a method name with Unit return type to make it a setter
Prepending a constructor parameter neither with val nor with var, makes it private
Then it follows:
val noArgFoo = Foo() // no argument case
println(noArgFoo.x) // the public getter prints 0
val withArgFoo = Foo(5) // with argument case
println(withArgFoo.x) // the public getter prints 5
noArgFoo.x = 100 // use the public setter to update x value
println(noArgFoo.x) // the public getter prints 100
withArgFoo.x = 1000 // use the public setter to update x value
println(withArgFoo.x) // the public getter prints 1000
This solution is exactly what you asked; in a principled way and without any ad hoc workaround e.g. using companion objects and the apply method.
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)
}
}