In Java I understand class fields as variables that are accessible from the whole everywhere in the class and that kind of describe the state-structure of instances. In Java field are defined outside any method (and this is the only thing that can be outside of methods).
In Scala "outside any method" is the main constructor - in other words: there is no "outside any method". Thus fields are defined in the main constructor. Thus any variable/value in the constructor is a field. Even arguments given to the constructor are automatically class fields and not local constructor variables as in Java.
In case I got all that right: Are there local variables/values in Scala constructors?
If not: Why was it decided that such a thing is not needed?
Clarficiation: I ask about concepts, not a specific case. Also I do not ask about how to work around to get something like local variables (although I would appreciate it if the answer were that there aren't any).
The entire class body is "the contructor".
You can always restrict the scope of any variable to be a small as you like with a pair of braces, so there is no reason to introduce an additional "concept", that serves no specific purpose. Occam's razor.
class Foo(bar: String) { // constructor parameter
val baz = "baz"; // class member
{
val bat = "bat" // "local" variable
println(bar + baz + bat) // all three are visible
}
println(bar + baz) // only first two are accessble
}
println (new Foo("bar").baz) // only class member can be accessed here
Related
Is there a compiler meta for Class declaration, that prevents creating Class instance before extending it? In other words - some sort of opposite of #:final meta.
Like so (last line of code):
class A {
// ...
}
class B extends A {
// ...
}
// ...
var b = new B(); // OK
var a = new A(); // induce compiler-error
Simply don't declare a constructor at all for class A
Both the other answers are correct (no constructor or private constructor), but there are a few more details that you may interest you:
Here's an example of no constructor. Of note is that A simply doesn't have a constructor, and B simply doesn't call super(). Other than that, everything else works as you'd expect.
Here's an example of a private constructor. You still can't instantiate a new A(), but you do still need to call super() from B's constructor.
Technicalities:
Use of some features (like a default value on a member variable) will cause A to get an implicit constructor, automatically. Don't worry, this doesn't affect constructability or whether you need to call super(). But know that it is there, and if necessary an implicit super() call is prepended to B's constructor. See the JS output to verify this.
In any case, know that you can still instantiate an A at runtime with var a = Type.createInstance(A,[]); as compile-time type checks do not limit RTTI.
Related discussion:
Aside from private/no constructor, Haxe doesn't have a formal notion of abstract classes1 (base classes not expected to be instantiated) or abstract methods2 (functions on abstract base classes with no implementation that must be implemented by a derived class.) However, Andy Li wrote a macro for enforcing some of those concepts if you use them. Such a macro can detect violations of these rules and throw compile-time errors.
1. Not to be confused with Haxe abstracts types, which are an entirely different topic.
2. Not to be confused with virtual functions, which wikipedia describes as a function which can be overridden (though various docs for various languages describe this highly loaded term differently.)
One way of achieving this is to create private Class constructor:
class A {
private function new() {
// ...
}
}
// ...
var a = new A(); // Error: Cannot access private constructor
I am trying to use global variable in Scala. to be accessible in the whole program .
val numMax: Int = 300
object Foo {.. }
case class Costumer { .. }
case class Client { .. }
object main {
var lst = List[Client]
// I would like to use Client as an object .
}
I got this error :
error: missing arguments for method apply in object List;
follow this method with `_' if you want to treat it as a partially applied function
var lst = List[A]
How can I deal with Global Variables in Scala to be accessible in the main program .
Should I use class or case class in this case ?
This isn't a global variable thing. Rather, you want to say this:
val lst = List(client1, client2)
However, I disagree somewhat with the other answers. Scala isn't just a functional language. It is both functional (maybe not as purely as it should be if you ask the Clojure fans) and object-oriented. Therefore, your OO expertise translates perfectly.
There is nothing wrong with global variables per se. The concern is mutability. Prefer val to var as I did. Also, you need to use object for singletons rather than the static paradigm you might be used to from Java.
The error you quote is unrelated to your attempt to create a global variable. You have missing () after the List[Client].
If you must create a global variable, you can put it in an object like Foo and reference it from other objects using Foo.numMax if the variable is called numMax.
However, global variables are discouraged. Maybe pass the data you need into the functions that need it instead. That is the functional way.
I have been looking at examples online, and tutorials, and I cannot find anything that explains how this (inheritance) differs from java. Simple example:
class Shape {
String type;
Shape(String type) {
this.type = type;
}
...
}
class Square extends Shape {
Square(String name){
Super(name);
}
....
}
Whats confusing me is in the above example I need to call the super class in order to set the 'type' variable, as well as to access it to tell me the Box objects' type as well. In Scala, how can this be done? I know scala uses traits interfaces as well, but is the above example omitted completely from scala? Can anyone direct me to a good example or explain it. I really appreciate it.
You can write almost exactly the same thing in Scala, much more concisely:
class Shape(var `type`: String)
class Square(name: String) extends Shape(name)
In the first line, the fact that type is preceded by var makes the compiler add getters and setters (from "5.3 Class Definitions" in the specification):
If a formal parameter declaration x : T is preceded by a val or
var keyword, an accessor (getter) definition (§4.2) for this parameter is implicitly added to the class. The getter introduces a value member x of class c that is defined as an alias of the parameter. If the introducing keyword is var, a setter accessor x _= (§4.2) is also implicitly added to the class.
In the second line name is not preceded by val or var, and is therefore just a constructor parameter, which is this case we pass on to the superclass constructor in the extends clause. No getters or setters are added for name, so if we created an instance square of Square and called square.name, it wouldn't compile.
Note also that type is a keyword in Scala, so I've had to surround it by backticks in both the definition and the example above:
Example 1.1.2 Backquote-enclosed strings are a solution when one needs to access Java identifiers that are reserved words in Scala.
There are many, many resource that you can read for more information about inheritance in Scala. See for example Chapters 4 and 5 of Programming Scala.
I am experiencing a weird behavior by Scala handling of superclass constructors.
I have a really simple class defined in the following way
package server
class Content(identifier:String,content:String){
def getIdentifier() : String = {identifier}
def getContent() : String = {content}
}
and a simple subclass
package server
class SubContent(identifier:String, content:String) extends Content(identifier, content+"XXX")){
override def getContent():String = {
println(content)
super.getContent
}
}
What's really strange is that in the subclass there are duplicates of the superclass attributes, so if i create a new object
var c = new SubContent("x","x")
the execution of
c.getContent
first prints out "x" (The valued provided to the subclass constructor), but returns "xXXX" (The value provided to the superclass constructor).
Is there any way to avoid this behavior? Basically what I'd like to have is that the subclass does not create its own attributes but rather just passes the parameters to the superclass.
It's doing exactly what you told it to do. You augmented the 2nd constructor parameter when passing it on to the superclass constructor and then you used the superclass' getContent to provide the value returned from the subclass' getContent.
The thing you need to be aware of is that constructor parameters (those not tied to properties because they're part of a case class or because they were declared with the val keyword) are in scope throughout the class body. The class' constructor is that part of its body that is outside any method. So references to constructor parameters in method bodies forces the constructor parameter to be stored in a field so it can have the necessary extent. Note that your println call in getContent is causing such a hidden constructor parameter field in this case.
Replying to comment "Is there an alternative way to define it in order to avoid this? Or at least, if I never refer to the parameters of the subclass constructors their fields will be allocated (Wasting memory)?":
If the only references to plain constructor parameters (*) is in the constructor proper (i.e., outside any method body, and val and var initializers don't qualify as method bodies) then no invisible field will be created to hold the constructor parameter.
However, If there's more you're trying to "avoid" than these invisible fields, I don't understand what you're asking.
(*) By "plain constructor parameters" I mean those not part of a case class and not bearing the val keyword.
I want to write class whose constructor takes two parameters, but the arguments are not actually members of the class. e.g.
class P(V1:Int, V2:Int) {
val set = Set(V1, V2)
}
Having constructed the 'set', I don't actually care about V1 and V2. Is there a way of expressing this in Scala ?
Well, exactly like that. If the constructor arguments are not tagged with val or var, nor the class is a case class, then they'll be kept allocated if used inside methods (or lazy val, I suppose). If used just in the constructor, they won't be allocated with the object, not even as private fields.