According to the docs here, declarations should be a subset of members for the things declared in the class, not inherited. Then why do various classes report no declarations?
scala> import scala.reflect.runtime.universe._
scala> typeTag[java.lang.System].tpe.declarations
res5: reflect.runtime.universe.MemberScope = SynchronizedOps()
The reason is that both members and declarations only take into account object members. However, all functions declared in java.lang.System are static.
This makes sense because from the scala point of view there are no static members. The equivalent of a static member is a method/value defined in a module (using object instead of class). So scala-reflection will act as if static members of a Java-class are defined in a module --- more specifically in the companion object of the java-class. (Note that in contrast to scala defined companion objects these "java-companion-objects" do not exist on a VM level).
I'm no expert in scala reflection, so I can't tell you how you would find the static members :-(
Related
I have read how companion and singleton objects can be used to keep static methods, which makes sense. My question is how is this object made or instantiated it? I have read from some sources on how Objects are instances of the class if used as companion objects while others say they are not instances of the class. Then how are the objects existing or being made? Plus the Object would be same class data type I suppose?
My question is how is this object made or instantiated it?
[β¦]
Then how are the objects existing or being made?
You don't know, shouldn't know, and can't know.
The Scala Language Specification says that they exist. The Scala Language Specification does not say how they are instantiated. Every implementor is free to implement them however they want.
For example, ECMAScript has object literals, so for Scala.js, there is no need for them to be an instance of any class at all. Scala-native is not dependent on any platform, so it can do whatever it wants. Scala-JVM needs to comply with the restrictions of the JVM, where every object needs to be an instance of a class. In Scala-JVM, every singleton object Foo is an instance of a JVM class named Foo$.
Plus the Object would be same class data type I suppose?
The type of a singleton object Foo is the singleton type Foo.type. It's not a class.
I have read from some sources on how Objects are instances of the class if used as companion objects while others say they are not instances of the class.
Instead of reading "some sources", it's much better to just read the source: the Scala Language Specification, specifically section 5.3.2 Case Classes:
A case class definition of π[tps](ps1)β¦(psπ) with type parameters tps and value parameters ps implies the definition of a companion object, which serves as an extractor object. It has the following shape:
object π {
def apply[tps](ps1)β¦(psπ): π[tps] = new π[Ts](xs1)β¦(xsπ)
def unapply[tps](π₯: π[tps]) =
if (x eq null) scala.None
else scala.Some(π₯.xs11,β¦,π₯.xs1π)
}
Each object has its own class, but you can't access the class directly. This class has a constructor without parameters which is called automatically when it's loaded and creates the only instance.
Objects are instances of the class if used as companion objects
Either you misunderstood or you really shouldn't trust these sources. It's possible for a companion object to extend the trait/class it's companion to, but not at all common.
Companion objects are not instances of the class they're companion of, think of them more like a collection of utility methods. If you're familiar with Java - all the method, that you made static in Java (hence they don't belong to a particular instance, but to class in general) would go to Companion object in Scala. Also, companion objects have access to classes private values.
Objects are lazily initialized for you, you don't need to know when and how exactly are they created, just if you call a function from an object - it will be created for you, and there will be only one instance of it.
Why are these type aliases and vals introduced in Predef?
Things that are in Predef are automatically imported. In Scala, you can write
val mySet : Set[String] = Set( "cat", "dog", "poop" )
without having to first write
import scala.collection.immutable.Set
Note that the declaration I wrote above might have been written equivalently as
val mySet : Set[String] = Set.apply( "cat", "dog, "poop" )
On the right-hand side of the equals sign, the word Set refers to a singleton object. We can only call methods on objects (whether singletons or instances of classes). We can't call methods on types. Somehow, we must have autoimported the name of an object Set. This is what the Predef declaration
val Set = immutable.Set
does.
If you are a Java programmer, you can think of a val declaration that just points to an object that would otherwise require the use of an import or a much longer name as being the equivalent of import static.
The Set[String] after the colon and before the equals sign is a type annotation. In this context Set[String] is a type. An object is not a type. If all we had declared in Predef were the val, our declaration could not compile. We would have been saying that mySet's type is a some particular object, but a type is very different from an object, a type is a description of a category to which an object may belong.
To let Set also serve as a type, we need the type alias
type Set[A] = immutable.Set[A]
If you are a java programmer, this functions similarly to a nonstatic import of a type name. (Scala has imports as well, but they must be scoped to a specific block or file. type aliases in Predef are available to all Scala files, so it does much more than an import of the type would do.)
The package scala.collection.immutable contains both an object, declared as
object Set{ ... }
and a type, declared as
trait Set[A]{ ... }
If we want to be able to use both the object (with its useful factory methods) and the type (the compile-time description of the objects our factory creates), we need to make both of them, object and type, available to our code. The two lines (for Set) that you quote above do precisely that. (And the other two lines do precisely the same for Map.)
These types and vals just make importing unnecessary, I believe.
The vals are assigning the companion objects into the vals - again, getting rid of an import.
I suspect they are done in this odd way to avoid a circular compile-time dependency between Predef.scala and Map/Set.scala, but I'm only guessing.
The whole point of Predef is to avoid explicit qualifications and import statements. From the docs:
The Predef object provides definitions that are accessible in all
Scala compilation units without explicit qualification.
Predef provides type aliases for types which are commonly used, such as the immutable collection types scala.collection.immutable.Map,
scala.collection.immutable.Set, and the
scala.collection.immutable.List constructors
(scala.collection.immutable.:: and scala.collection.immutable.Nil).
This way, you can refer to Map without having to explicitly qualify or import scala.collection.immutable.Map.
scala> object Test
defined module Test
Why is the defined object Test called 'module', not companion object, by the scala interpreter ?
Is there a difference between module and companion object or is it just the same with two different names ?
Technically, there is only one such thing, in the language specification it is mostly called 'module', but you also find this statement: "The object definition defines a single object (or: module) ..." (Scala Language Specification)
Furthermore, you can only speak of a companion object, when it actually accompanies something:
"Generally, a companion module of a class is an object which has the same name as the class and is defined in the same scope and compilation unit. Conversely, the class is called the companion class of the module." (again think: companion object = companion module)
Being in companion state adds features to the companion class, namely visibility (e.g., the class can see the private fields of the companion module). Same scope and compilation unit means, they need to be defined in the same source file and same package.
There is an interesting thread on LtU where Scala's object versus module terminology is discussed. It contains also a link to a paper by Odersky and Zenger if you are intrigued; showing how they particularly looked at the ML language's module system (OCaml being a major influence on Scala), and how they frame it as various approaches of modular composition (suggesting that module is a more generic concept; traits as mixin modules, ...)
Suppose MyClass is a class defined in Java, and has many static as well as non-static members. I tried to alias this class (and associated companion object) in a Scala object MyObject as shown below:
object MyObject {
import javastuff._
type MyAlias = MyClass
val MyAlias = MyClass
}
Scalac complains:
error: object MyClass is not a value
val MyAlias = MyClass
How do I work around this? Thanks.
Although this works in pure Scala for a class + companion object, it's not possible with Java's static methods, as these don't belong to any interface.
Scala could, in theory, create an object containing delegates to all the static methods of some class, but it doesn't do this currently. It's also possible to write a compiler plugin for this if you feel comfortable writing plugins.
Failing that, you'll either have to create an object full of delegates yourself, or just cherry-pick a few methods and pass them around as functions.
it's not possible with Java's static methods, as these don't belong to any interface.
Update 5 years later: PR 5131 mentions:
We used to disable generation of static forwarders when a object had a
trait as a companion, as one could not add methods with bodies to an
interface in JVM 6.
The JVM lifted this restriction to support default methods in interfaces,
so we can lift the restriction on static forwarders, too.
Fixes scala-dev issue 59
See commit 41c9a17 by Jason Zaugg (retronym).
Coming from Java I am confused by the class/object distinction of scala.
Note that I do not ask for the formal difference; there are enough
references on the web which explain this, and there are related questions on
SO.
My questions are:
Why did the designers of scala
choosed to make things more
complicated (compared to Java or
C#)? What disadvantages do I have to
expect if I ignore this distinction
and declare only classes?
Thanks.
Java classes contain two completely different types of members -- instance members (such as BigDecimal.plus) and static members (such as BigDecimal.valueOf). In Scala, there are only instance members. This is actually a simplification! But it leaves a problem: where do we put methods like valueOf? That's where objects are useful.
class BigDecimal(value: String) {
def plus(that: BigDecimal): BigDecimal = // ...
}
object BigDecimal {
def valueOf(i: Int): BigDecimal = // ...
}
You can view this as the declaration of anonymous class and a single instantiation thereof:
class BigDecimal$object {
def valueOf(i: Int): BigDecimal = // ...
}
lazy val BigDecimal = new BigDecimal$object
When reading Scala code, it is crucial to distinguish types from values. I've configured IntelliJ to hightlight types blue.
val ls = List.empty[Int] // List is a value, a reference the the object List
ls: List[Int] // List is a type, a reference to class List
Java also has another degree of complexity that was removed in Scala -- the distinction between fields and methods. Fields aren't allowed on interfaces, except if they are static and final; methods can be overriden, fields instead are hidden if redefined in a subclass. Scala does away with this complexity, and only exposes methods to the programmer.
Finally, a glib answer to your second question: If you don't declare any objects, you're program may never run, as you to define the equivalent of public static void main(String... args) {} in Scala, you need at least one object!
Scala doesn't have any notion of static methods with standard classes, so in those scenarios you'll have to use objects. Interesting article here which provides a good intro:
http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-3
(scroll down to Scalaβs Sort-of Statics)
One way to look at it is this. An executing program consists of a community of objects and threads. Threads execute code within the context of objects -- i.e. there is always a "this" object that a thread is executing within. This is a simplification from Java in the sense that in Java, there is not always a "this". But now there is a chicken/egg problem. If objects are created by threads and threads are executed within objects, what object is the first thread initially executing within. There has to be a nonempty set of objects that exist at the start of program execution. These are the objects declared with the object keyword.