Does scala provide a default apply method for a class?
I have a class:
class Player(tea: String, sal: Int = 0) {
val team = tea
private val salary = sal
}
So no apply method here, and I haven't defined any companion object for it, so no apply method from there too.
But I am able to do:
val player = Player("AAAA", 1000)
With no 'new' operator used, I understand that this line of code must invoke some apply method. But there is none defined by me. So how does it work?
Yes, since Scala 3, as described in the docs:
Scala case classes generate apply methods, so that values of case classes can be created using simple function application, without needing to write new.
Scala 3 generalizes this scheme to all concrete classes. Example:
class StringBuilder(s: String):
def this() = this("")
StringBuilder("abc") // old: new StringBuilder("abc")
StringBuilder() // old: new StringBuilder()
This works since a companion object with two apply methods is generated together with the class. The object looks like this:
object StringBuilder:
inline def apply(s: String): StringBuilder = new StringBuilder(s)
inline def apply(): StringBuilder = new StringBuilder()
The synthetic object StringBuilder and its apply methods are called constructor proxies. Constructor proxies are generated even for Java classes and classes coming from Scala 2. The precise rules are as follows:
A constructor proxy companion object object C is created for a concrete class C, provided the class does not have already a companion, and there is also no other value or method named C defined or inherited in the scope where C is defined.
Constructor proxy apply methods are generated for a concrete class provided
the class has a companion object (which might have been generated in step 1), and
that companion object does not already define a member named apply.
Each generated apply method forwards to one constructor of the class. It has the same type and value parameters as the constructor.
In my study of Scala I ran into the following snippet:
val r = Random
Now from my understanding from Alvin Alexander's excellent post (How to create Scala object instances without using the “new” keyword (apply) you can create a new Scala object instance without using the new keyword as follows:
Create a companion object for your class, and define an apply method
in the companion object with the desired constructor signature.
Define your class as a “case class.”
However, when I look at the source code for the Random class (Scala 2.12.8) I see that it is not a case class nor does the companion object have the apply method in its companion object.
Could someone please explain to me why it's valid syntax to create a Random as posted above even though it doesn't meet the requirements as described in Alvin Alexander's post?
Thanks!
In this context Random is a singleton instance of class Random
object Random extends Random
where
class Random(val self: java.util.Random) extends ... {
...
def this() = this(new java.util.Random())
...
}
hence it is already a value. For example consider the following
class Foo(val v: Int)
object Foo extends Foo(42)
Foo.v
which outputs
res0: Int = 42
Note how Foo in Foo.v is already referencing an instance singleton value of class Foo. Hence r in
val r = Random
is simply referencing existing singleton value. It is akin to
val a = 11
val r = a
Simply put: you are not creating a new instance of the Random class, you are assigning the existing instance of the Random class which also happens to be called Random to the field r.
It might sound confusing that there is both a class and an object named Random but there actually cannot possibly be any confusion, since in Scala, types and terms live in different "worlds" and their names can never mix.
Note that it is in fact quite common to have a class or trait and an object with the same name, for the following reason:
if an object has the same name as a class or trait, and
that object is defined in the same scope as the class or trait with the same name, and
that object is defined in the same compilation unit as the class or trait with the same name, then
that object is called a companion module and has privileged access to the internals of the class or trait.
I have created a companion object for my Scala class with an apply method in it so that I can create an instance of my class without using 'new'.
object StanfordTokenizer{
def apply() = new StanfordTokenizer()
}
class StanfordTokenizer() extends Tokenizer{
def tokenizeFile(docFile: java.io.File) = new PTBTokenizer(new FileReader(docFile), new CoreLabelTokenFactory(), "").tokenize.map(x => x.word().toLowerCase).toList
def tokenizeString(str: String) = new PTBTokenizer(new StringReader(str), new CoreLabelTokenFactory(), "").tokenize.map(x => x.word.toLowerCase()).toList
}
However when I try to instantiate the StanfordTokenizer class without 'new' e.g. StandfordTokenizer.tokenizeString(str).
I get the error
value tokenizeString is not a member of object StanfordTokenizer
However, if I explicitly include the apply method like StandfordTokenizer.apply().tokenizeString(str) it does work.
I feel like I am missing something fundamental about companion objects. Can someone shed some light on this for me?
^
It's exactly as the compiler message says. tokenizeString is a member of the class StandfordTokenizer, but not its companion object. The companion object does not inherit any methods from the class. Therefore, in order to use tokenizeString, you need an instance of StandfordTokenizer in order to call it.
StandfordTokenizer.apply creates an instance of the class StandfordTokenizer, which has the method tokenizeString. It seems as though the class StandfordTokenizer holds no real information, and won't have more than one instance. If that is true, you should probably just make it an object, and you'll be able to acquire the behavior you're looking for.
object StanfordTokenizer extends Tokenizer {
def tokenizeFile(docFile: java.io.File) = ...
def tokenizeString(str: String) = ...
}
This should work as well (as a class):
StandfordTokenizer().tokenizeString(str)
StandfordTokenizer without parenthesis does not call apply, it references the object. StandfordTokenizer() does call apply, and creates a new instance of the class. This is probably the source of your confusion.
This is a follow up to the following question, which concerned serialization: How best to keep a cached list of member fields, one each for a family of case classes in Scala
I'm trying to generically support deserialization in the same way. One straightforward attempt is the following:
abstract class Serializer[T](implicit ctag: ClassTag[T]) {
private val fields = ctag.runtimeClass.getDeclaredFields.toList
fields foreach { _.setAccessible(true) }
implicit class AddSerializeMethod(obj: T) {
def serialize = fields.map(f => (f.getName, f.get(obj)))
}
def deserialize(data: List[(String, Any)]): T = {
val m = data toMap
val r: T = ctag.runtimeClass.newInstance // ???
fields.foreach { case f => f.set(r, m(f.getName)) }
r;
}
}
There are a couple of issues with the code:
The line with val r: T = ... has a compile error because the compiler thinks it's not guaranteed to have the right type. (I'm generally unsure of how to create a new instance of a generic class in a typesafe way -- not sure why this isn't safe since the instance of Serializer is created with a class tag whose type is checked by the compiler).
The objects I'm creating are expected to be immutable case class objects, which are guaranteed to be fully constructed if created in the usual way. However, since I'm mutating the fields of instances of these objects in the deserialize method, how can I be sure that the objects will not be seen as partially constructed (due to caching and instruction reordering) if they are published to other threads?
ClassTag's runtimeClass method returns Class[_], not Class[T], probably due to the fact generics in Scala and Java behave differently; you can try casting it forcefully: val r: T = ctag.runtimeClass.newInstance.asInstanceOf[T]
newInstance calls the default, parameterless constructor. If the class doesn't have one, newInstance will throw InstantiationException. There's no way around it, except for:
looking around for other constructors
writing custom serializers (see how Gson does that; BTW Gson can automatically serialize only classes with parameterless constructors and those classes it has predefined deserializers for)
for case classes, finding their companion object and calling its apply method
Anyhow, reflection allows for modifying final fields as well, so if you manage to create an immutable object, you'll be able to set its fields.
I'm just going over some Scala tutorials on the Internet and have noticed in some examples an object is declared at the start of the example.
What is the difference between class and object in Scala?
tl;dr
class C defines a class, just as in Java or C++.
object O creates a singleton object O as instance of some anonymous class; it can be used to hold static members that are not associated with instances of some class.
object O extends T makes the object O an instance of trait T; you can then pass O anywhere, a T is expected.
if there is a class C, then object C is the companion object of class C; note that the companion object is not automatically an instance of C.
Also see Scala documentation for object and class.
object as host of static members
Most often, you need an object to hold methods and values/variables that shall be available without having to first instantiate an instance of some class.
This use is closely related to static members in Java.
object A {
def twice(i: Int): Int = 2*i
}
You can then call above method using A.twice(2).
If twice were a member of some class A, then you would need to make an instance first:
class A() {
def twice(i: Int): Int = 2 * i
}
val a = new A()
a.twice(2)
You can see how redundant this is, as twice does not require any instance-specific data.
object as a special named instance
You can also use the object itself as some special instance of a class or trait.
When you do this, your object needs to extend some trait in order to become an instance of a subclass of it.
Consider the following code:
object A extends B with C {
...
}
This declaration first declares an anonymous (inaccessible) class that extends both B and C, and instantiates a single instance of this class named A.
This means A can be passed to functions expecting objects of type B or C, or B with C.
Additional Features of object
There also exist some special features of objects in Scala.
I recommend to read the official documentation.
def apply(...) enables the usual method name-less syntax of A(...)
def unapply(...) allows to create custom pattern matching extractors
if accompanying a class of the same name, the object assumes a special role when resolving implicit parameters
A class is a definition, a description. It defines a type in terms of methods and composition of other types.
An object is a singleton -- an instance of a class which is guaranteed to be unique. For every object in the code, an anonymous class is created, which inherits from whatever classes you declared object to implement. This class cannot be seen from Scala source code -- though you can get at it through reflection.
There is a relationship between object and class. An object is said to be the companion-object of a class if they share the same name. When this happens, each has access to methods of private visibility in the other. These methods are not automatically imported, though. You either have to import them explicitly, or prefix them with the class/object name.
For example:
class X {
// class X can see private members of object X
// Prefix to call
def m(x: Int) = X.f(x)
// Import and use
import X._
def n(x: Int) = f(x)
private def o = 2
}
object X {
private def f(x: Int) = x * x
// object X can see private members of class X
def g(x: X) = {
import x._
x.o * o // fully specified and imported
}
}
An object has exactly one instance (you can not call new MyObject). You can have multiple instances of a class.
Object serves the same (and some additional) purposes as the static methods and fields in Java.
As has been explained by many, object defines a singleton instance. The one thing in the answers here that I believe is left out is that object serves several purposes.
It can be the companion object to a class/trait, containing what might be considered static methods or convenience methods.
It can act much like a module, containing related/subsidiary types and definitions, etc.
It can implement an interface by extending a class or one or more traits.
It can represent a case of a sealed trait that contains no data. In this respect, it's often considered more correct than a case class with no parameters. The special case of a sealed trait with only case object implementors is more or less the Scala version of an enum.
It can act as evidence for implicit-driven logic.
It introduces a singleton type.
It's a very powerful and general construct. What can be very confusing to Scala beginners is that the same construct can have vastly different uses. And an object can serve many of these different uses all at once, which can be even more confusing.
Defining an object in Scala is like defining a class in Java that has only static methods. However, in Scala an object can extend another superclass, implement interfaces, and be passed around as though it were an instance of a class. (So it's like the static methods on a class but better).
The formal difference -
you can not provide constructor parameters for Objects
Object is not a type - you may not create an instance with new operator. But it can have fields, methods, extend a superclass and mix in traits.
The difference in usage:
Scala doesn't have static methods or fields. Instead you should use object. You can use it with or without related class. In 1st case it's called a companion object. You have to:
use the same name for both class and object
put them in the same source file.
To create a program you should use main method in object, not in class.
object Hello {
def main(args: Array[String]) {
println("Hello, World!")
}
}
You also may use it as you use singleton object in java.
In scala, there is no static concept. So scala creates a singleton object to provide entry point for your program execution.
If you don't create singleton object, your code will compile successfully but will not produce any output. Methods declared inside Singleton Object are accessible globally. A singleton object can extend classes and traits.
Scala Singleton Object Example
object Singleton{
def main(args:Array[String]){
SingletonObject.hello() // No need to create object.
}
}
object SingletonObject{
def hello(){
println("Hello, This is Singleton Object")
}
}
Output:
Hello, This is Singleton Object
In scala, when you have a class with same name as singleton object, it is called companion class and the singleton object is called companion object.
The companion class and its companion object both must be defined in the same source file.
Scala Companion Object Example
class ComapanionClass{
def hello(){
println("Hello, this is Companion Class.")
}
}
object CompanoinObject{
def main(args:Array[String]){
new ComapanionClass().hello()
println("And this is Companion Object.")
}
}
Output:
Hello, this is Companion Class.
And this is Companion Object.
In scala, a class can contain:
1. Data member
2. Member method
3. Constructor Block
4. Nested class
5. Super class information etc.
You must initialize all instance variables in the class. There is no default scope. If you don't specify access scope, it is public. There must be an object in which main method is defined. It provides starting point for your program. Here, we have created an example of class.
Scala Sample Example of Class
class Student{
var id:Int = 0; // All fields must be initialized
var name:String = null;
}
object MainObject{
def main(args:Array[String]){
var s = new Student() // Creating an object
println(s.id+" "+s.name);
}
}
I am sorry, I am too late but I hope it will help you.
The object keyword creates a new singleton type, which is like a class that only has a single named instance. If you’re familiar with Java, declaring an object in Scala is a lot like creating a new instance of an anonymous class.
Scala has no equivalent to Java’s static keyword, and an object is often used in Scala where you might use a class with static members in Java.
Object is a class but it already has(is) an instance, so you can not call new ObjectName. On the other hand, Class is just type and it can be an instance by calling new ClassName().
A class is just like any other class in other languages. You define class just like any other language with some syntax difference.
class Person(val name: String)
val me = new Person("My name")
However, object is a class with single object only. This makes it interesting as it can be used to create static members of a class using companion object. This companion object has access to private members of the class definition and it has the same name as the class you're defining.
class Person(var name: String) {
import Person._
def hi(): String = sayHello(name)
}
object Person {
private def sayHello(name: String): String = "Hello " + name
}
val me = new Person("My name")
me.hi()
Also, noteworthy point is that object class is lazily created which is another important point. So, these are not instantiated unless they are needed in our code.
If you're defining connection creation for JDBC, you can create them inside object to avoid duplication just like we do in Java with singleton objects.
Scala class same as Java Class but scala not gives you any entry method in class, like main method in java. The main method associated with object keyword. You can think of the object keyword as creating a singleton object of a class that is defined implicitly.
more information check this article
class and object keyword in scala programming
The object is similar to the static class in Java to some extend, the static characteristic means the static class need not to create an object when putting to the JVM, it can be used by it's class name directly and the same instance(same data state) is shared wherever it is used.
If you are coming from java background the concept of class in scala is kind of similar to Java, but class in scala cant contain static members.
Objects in scala are singleton type you call methods inside it using object name, in scala object is a keyword and in java object is a instance of class