Given the following:
class TestClass extends TestTrait {
def doesSomething() = methodValue + intValue
}
trait TestTrait {
val intValue = 4
val unusedValue = 5
def methodValue = "method"
def unusedMethod = "unused method"
}
When the above code runs, will TestClass actually have memory allocated to unusedValue or unusedMethod? I've used javap and I know that there exists an unusedValue and an unusedMethod, but I cannot determine if they are actually populated with any sort of state or memory allocation.
Basically, I'm trying to understand if a class ALWAYS gets all that a trait provides, or if the compiler is smart enough to only provide what the class actually uses from the trait?
If a trait always imposes itself on a class, it seems like it could be inefficient, since I expect many programmers will use traits as mixins and therefore wasting memory everywhere.
Thanks to all who read and help me get to the bottom of this!
Generally speaking, in languages like Scala and Java and C++, each class has a table of pointers to its instance methods. If your question is whether the Scala compiler will allocate slots in the method table for unusedMethod then I would say yes it should.
I think your question is whether the Scala compiler will look at the body of TestClass and say "whoa, I only see uses of methodValue and intValue, so being a good compiler I'm going to refrain from allocating space in TestClass's method table for unusedMethod. But it can't really do this in general. The reason is, TestClass will be compiled into a class file TestClass.class and this class may be used in a library by programmers that you don't even know.
And what will they want to do with your class? This:
var x = new TestClass();
print(x.unusedMethod)
See, the thing is the compiler can't predict who is going to use this class in the future, so it puts all methods into its method table, even the ones not called by other methods in the class. This applies to methods declared in the class or picked up via an implemented trait.
If you expect the compiler to do global system-wide static analysis and optimization over a fixed, closed system then I suppose in theory it could whittle away such things, but I suspect that would be a very expensive optimization and not really worth it. If you need this kind of memory savings you would be better off writing smaller traits on your own. :)
It may be easiest to think about how Scala implements traits at the JVM level:
An interface is generated with the same name as the trait, containing all the trait's method signatures
If the trait contains only abstract methods, then nothing more is needed
If the trait contains any concrete methods, then the definition of these will be copied into any class that mixes in the trait
Any vals/vars will also get copied verbatim
It's also worth noting how a hypothetical var bippy: Int is implemented in equivalent java:
private int bippy; //backing field
public int bippy() { return this.bippy; } //getter
public void bippy_$eq(int x) { this.bippy = x; } //setter
For a val, the backing field is final and no setter is generated
When mixing-in a trait, the compiler doesn't analyse usage. For one thing, this would break the contract made by the interface. It would also take an unacceptably long time to perform such an analysis. This means that you will always inherit the cost of the backing fields from any vals/vars that get mixed in.
As you already hinted, if this is a problem then the solution is just use defs in your traits.
There are several other benefits to such an approach and, thanks to the uniform access principle, you can always override such a method with a val further down in the inheritance hierarchy if you need to.
Related
I created a class extend scala.Immutable
class SomeThing(var string: String) extends Immutable {
override def toString: String = string
}
As I expected, scala compiler should help me prevent change state of class SomeThing. But when I run this test
"Test change state of immutable interface" should "not allow" in {
val someThing = new SomeThing("hello")
someThing.string = "hello 1"
println(someThing)
}
The result is hello 1 and scala compiler don't throw any warning or error.
Why they have to add Immutable trait without help us prevent object mutable?
There are several aspects to this question.
1. A simple one is that Scala compiler can't really ensure immutability for many various reasons. For example, the main target platform JVM allows modifying even final fields using reflection. Another reason this is not enforceable is code like this
/////////////////////////////////////////
//// library v1
package library
class LibraryData(val value:Int)
/////////////////////////////////////////
//// code that uses the library
package app
class UserData(val data:LibraryData) extends Immutable
/////////////////////////////////////////
//// library v2
package library
class LibraryData(var value:Int) //now change it to var!
Since the "library" is compiled independently of the "app" and doesn't even know about existence of the "app" there is no point in time where compiler can catch the broken contract.
2. More fundamental misunderstanding you seem to have is what trait does. In this context trait (or "interface" in some other languages) represents a contract between the implementation and the user-code about how the implementation can and should behave. However not every kind of a contract can be represented as a trait (at least without making the code super-complicated). For example, for a mutable collection there is a contract that size should return the number of times add (or +=) has been called but there is no way to represent such a contract as a trait besides declaring that there are methods size and += with corresponding signatures. On the other hand, for most of the contracts there is no way to enforce implementation to follow the contract . For example, an implementation of size that always returns 0 technically matches all the types but is clearly breaking the contract.
Similarly Immutable doc says:
A marker trait for all immutable data structures such as immutable collections.
So it is just a marker trait which is one of the ways to work around contracts that can't be really represented as types. And it says that whoever implements that trait claims to be an immutable object. Your code claims that but clearly breaks the contract. So technically it is your fault for not respecting the contract.
In the Scala spec, it's said that in a class template sc extends mt1, mt2, ..., mtn
Each trait reference mti must denote a trait. By contrast, the
superclass constructor sc normally refers to a class which is not a
trait. It is possible to write a list of parents that starts with a
trait reference, e.g. mt1 with …… with mtn. In that case the
list of parents is implicitly extended to include the supertype of
mt1 as first parent type. The new supertype must have at least one
constructor that does not take parameters. In the following, we will
always assume that this implicit extension has been performed, so that
the first parent class of a template is a regular superclass
constructor, not a trait reference.
If I understand it correctly, I think it means:
trait Base1 {}
trait Base2 {}
class Sub extends Base1 with Base2 {}
Will be implicitly extended to:
trait Base1 {}
trait Base2 {}
class Sub extends Object with Base1 with Base2 {}
My questions are:
Is my understanding correct?
Does this requirement (the first subclass in the parent list must be non-trait class) and the implicit extension only applies to class template (e.g. class Sub extends Mt1, Mt2) or also trait template (e.g. trait Sub extends Mt1, Mt2)?
Why this requirement and the implicit extension is necessary?
Disclaimer: I'm not and never was a member of the "Scala design committee" or anything like that, so the answer on the "why?" question is mostly speculation but I think a useful one.
Disclaimer #2: I've written this post over several hours and in several takes so it is probably not very consistent
Disclaimer #3 (a shameful self-promotion for the future readers): If you find this quite long answer useful, you might also take a look at my another long answer to another question by Lifu Huang on a similar topic.
Short answers
This is one of those complicated things for which I don't think there is a good short answer unless you already know what the answer is. Although my real answer will be long, here are my best short answers:
Why the first base class in parent list must be non-trait class?
Because there has to be only one non-trait base class and it makes thing easier if it is always the first
Is my understanding correct?
Yes, your implicit example is what will happen. However I'm not sure that it shows full understanding of the topic.
Does this requirement (the first subclass in the parent list must be non-trait class) and the implicit extension only applies to class template (e.g. class Sub extends Mt1, Mt2) or also trait template (e.g. trait Sub extends Mt1, Mt2)?
No, implicit extensions happens for traits as well. Actually how else you could expect Mt1 to have its own "supertype" to be promoted down to the class that extends it?
Actually here are two IMHO non-obvious examples proving this is true:
Example #1
trait TAny extends Any
trait TNo
// works
class CGood(val value: Int) extends AnyVal with TAny
// fails
// illegal inheritance; superclass AnyVal is not a subclass of the superclass Object
class CBad(val value: Int) extends AnyVal with TNo
This example fails because the spec says
The extends clause extends scsc with mt1mt1 with …… with mtnmtn can be omitted, in which case extends scala.AnyRef is assumed.
so TNo actually extends AnyRef which is incompatible with AnyVal.
Example #2
class CFirst
class CSecond extends CFirst
// did you know that traits can extend classes as well?
trait TFirst extends CFirst
trait TSecond extends CSecond
// works
class ChildGood extends TSecond with TFirst
// fails
// illegal inheritance; superclass CFirst is not a subclass of the superclass CSecond of the mixin trait TSecond
class ChildBad extends TFirst with TSecond
Again ChildBad fails because TSecond requires CSecond but TFirst only provides CFirst as the base class.
Why this requirement and the implicit extension is necessary?
There are three major reasons:
Compatibility with the main target platform (JVM)
Traits have "mixin" semantics: you have a class and you mix additional behavior in
Completeness, consistency and simplicity of the rest of the spec (e.g. of linearization rules). This might be restated as following: each class must declare 0 or 1 base non-trait classes and after compilation the target platform enforces that there will be exactly 1 non-trait base class. So it makes the rest of the spec easier if you just assume there is always exactly one base class. In such way you have to write this implicit extension rules only once rather than each time when the behavior depends on the base class.
Scala spec goals/intentions
I believe that when one reads a spec there are two different sets of questions:
What exactly is written? What is the meaning of the spec?
Why it is written so? What was the intention?
Actually I think in many cases #2 is more important than #1 but unfortunately specs rarely explicitly contain insights into that area. Anyway I will start with my speculations over #2: what were the intentions/goals/limitations of the classes system in Scala? The main high-level goal was to create a type system richer than the one in Java or .Net (which are quite similar) but that can be:
compiled back to an efficient code in those target platforms
allow reasonable two-way interaction between the Scala code and the "native" code in the target platforms
Side note: Support of the .Net was dropped years ago but it was one of the target platforms for years and this affected the design.
Single base class
Short summary: this section describes some reasons why Scala designers had a strong motivation to have the "exactly one base class" rule in the language.
A major problem with OO design and particularly inheritance is that AFAIK the question: "where exactly is the border between the "good and useful" practices and the "bad" ones?" is open. It means that each language must find out its own trade off between making impossible what is wrong and making possible (and easy) what is useful. Many believe that in C++, which obviously was a major inspiration for Java and .Net, that trade off is shifted too much into "allow everything even if it is potentially harmful" zone. It made many designers of newer languages to seek for more restricting trade off. Particularly both JVM and .Net platform enforce the rule that all types are split into "value types" (aka primitive types), "classes" and "interfaces" and each class, except the root class (java.lang.Object/System.Object), has exactly one "base class" and zero or more "base interfaces". This decision was a reaction to many issues of multiple inheritance including infamous "diamond problem" but actually many others as well.
Sidenote (about memory layout): Another major problem with multiple inheritance is objects layout in memory. Consider following ridiculous (and impossible in current Scala) example inspired by Achilles and the tortoise:
trait Achilles {
def getAchillesPos: Int
def stepAchilles(): Unit
}
class AchillesImpl(var achillesPos: Int) extends Achilles {
def getAchillesPos: Int = achillesPos
def stepAchilles(): Unit = {
achillesPos += 2
}
}
class TortoiseImpl(var tortoisePos: Int) {
def getTortoisePos: Int = tortoisePos
def stepTortoise(): Unit = {
tortoisePos += 1
}
}
class AchillesAndTortoise(handicap: Int) extends AchillesImpl(0) with TortoiseImpl(handicap) {
def catchTortoise(): Int = {
var time = 0
while (getAchillesPos < getTortoisePos) {
time += 1
stepAchilles()
stepTortoise()
}
time
}
}
The tricky part here is how to actually lay achillesPos and tortoisePos fields out in the memory (of the object). The issue is that you probably want to have only one compiled copy of all the methods in the memory and you want the code to be efficient. This means that getAchillesPos and stepAchilles should have know some fixed offset of the achillesPos regarding to the this pointer. Similarly getTortoisePos and stepTortoise should have know some fixed offset of the tortoisePos regarding to the this pointer. And all choices you have to achieve this goal don't look nice. For example:
You might decide that achillesPos is always first and tortoisePos is always second. But this means that in the instances of TortoiseImpl tortoisePos should also be the second field but there is nothing to fill the first field with so you waste some memory. Moreover if both AchillesImpl and TortoiseImpl come from pre-compiled libraries, you should have some way to move access to the fields in them as well.
You might try to "fix" this pointer on-the-fly when you call into TortoiseImpl (AFAIK this is the way C++ really works). This becomes especially funny when TortoiseImpl is an abstract class that is aware of the trait Achilles (but not the specific class AchillesImpl) via extends and tries to call back some methods from there via this or pass this to some method that takes Achilles as an argument so this has to be "fixed back". Note that this is not the same as the "diamond problem" because there is only one copy of all fields and implementations.
You might agree to have a unique copy of the methods compiled for each specific class that are aware of the specific layout. This is bad for memory usage and performance because it blows CPU caches and forces JIT to make independent optimizations for each.
You might say that no method except for getter and setter can have direct access to the fields and should use getters and setters instead. Or store all the fields in some kind of a dictionary which is effectively the same. This might be bad for performance (but this is the closest to what Scala does with mixin-traits).
In the actual Scala this issue does not exist because trait can't really declare any fields. When you declare val or var in a trait, you actually declare a getter (and a setter) method(s) that will be implemented by particular class that extends the trait and each class has full control over layout of the fields. And actually in terms of performance this most probably would work OK because JVM (JIT) can inline such a virtual call in many real-world scenarios.
End of the Sidenote
Another major point is interoperability with the target platform. Even if Scala somehow supported true multiple-inheritance so you can have a type that inherits from String with Date and that can be passed to both methods that expect String and that expect Date, how this would look like from the Java point of view? Also if the target platform enforces the rule that every class has to be an (indirect) sub-type of the same root class (Object), you can't work this around in your higher level language.
Traits and Mix-ins
Many think that "one class and many interfaces" trade-off that was made in Java and .Net is too restrictive. For example it makes it hard to share common default implementation of some of the interface methods between different classes. Actually over the time Java and .Net designers seem to come to the same conclusion and rolled out they own fixes for this kind of issues: Extension methods in .Net and then Default methods in Java. Scala designers added a feature called Mixins that was known to fare well in many practical cases. However unlike many other dynamic languages that has similar feature, Scala still had to meet the "exactly one base class" rule and other limitations of the target platform.
It is important to note that there are important scenarios when mixins are used in practice is to implement a variation of the Decorator or Adapter patterns both of which relies on the fact that you can restrict your base type to something more specific than Any or AnyRef. Prime example of such usage is the scala.collection package.
Scala syntax
So now you have following goals/restrictions:
Exactly one base class for each class
Ability to add logic to classes from mixins
Support of mixins with restricted base type
Classes from the target platform (Java) when seen from Scala are mapped to the Scala classes (because what else they can be mapped to?) and they come pre-compiled and we don't want to mess with their implementation
Other good qualities such as simplicity, type safety, determinism, etc.
If you want some kind of multiple inheritance support in your language, you need to develop conflict resolution rules: what happens when several base types provide some logic that would fit the same "slot" in your class. After prohibition of fields in traits we are left with the following "slots":
Base class in terms of the target platform
Constructors
Methods with the same name and signature
And possible conflict resolution strategies are:
Prohibit (fail compilation)
Decide which one wins and wipes others
Somehow chain them
Somehow preserve all with renaming. This is not really possible in JVM. For example in .Net see Explicit Interface Implementation
In a sense Scala uses all available (i.e. first 3) strategies but the high-level goal is: let's try to preserve as many logic as we can.
The most important part for this discussion is conflicts resolution for constructors and methods.
We want the rules to be the same for different slots because otherwise it is not clear how to achieve safety (if traits A and B both override methods foo and bar but resolution rules for foo and bar are different, invariants for A and B might easily be broken). Scala's approach is based on the class linearization. In short these is the way to "flatten" hierarchy of the base classes into a simple linear structure in some predictive way that is based on the idea that the lefter type in the with chain - the more "base" (higher in the inheritance) it is. After you do this, conflict resolution rule for methods becomes simple: you go through the list of the base types and chain behavior via super calls; if super is not called, you stop chaining. This produce quite predictable semantics that people can reason about.
Now assume you allow non-trait class to be not first. Consider following example:
class CBase {
def getValue = 2
}
trait TFirst extends CBase {
override def getValue = super.getValue + 1
}
trait TSecond extends CFirst {
override def getValue = super.getValue * 2
}
class CThird extends CBase with TSecond {
override def getValue = 100 - super.getValue
}
class Child extends TFirst with TSecond with CThird
In which order TFirst.getValue and TSecond.getValue should be called? Obviously CThird is already compiled and you can't change what the super for it is, so it has to be moved to the first position and there is already TSecond.getValue call inside it. But on the other hand this breaks the rule that everything on the left is base and everything on the right is child. The simplest way to not introduce such confusion is to enforce the rule that non-trait classes must go first.
The same logic applies if you just extend the previous example by substituting class CThird with a trait that extends it:
trait TFourth extends CThird
class AnotherChild extends TFirst with TSecond with TFourth
Again, the only non-trait class AnotherChild can extend is CThird and this again makes conflict resolution rules quite hard to reason about.
That's why Scala makes a rule much simpler: whatever provides the base class must come from the first position. And then it makes sense to extend the same rule upon the traits as well so if the first position is occupied by some trait - it also defines the base class.
1) Basically yes, your understanding is correct. Like in Java, every class inherits from java.lang.Object (AnyRef in Scala). So, since you are defining a concrete class, you will implicitly inherits from Object. If you check with the REPL, you got:
scala> trait Base1 {}
defined trait Base1
scala> trait Base2 {}
defined trait Base2
scala> class Sub extends Base1 with Base2 {}
defined class Sub
scala> classOf[Sub].getSuperclass
res0: Class[_ >: Sub] = class java.lang.Object
2) Yes, from the "Traits" paragraph in the specs, this applies also to them. In "Templates" paragraph we have:
The new supertype must have at least one constructor that does not take parameters
And then in "Traits" paragraph:
Unlike normal classes, traits cannot have constructor parameters. Furthermore, no constructor arguments are passed to the superclass of the trait. This is not necessary as traits are initialized after the superclass is initialized.
Assume a trait D defines some aspect of an instance x of type C (i.e. D is a base class of C). Then the actual supertype of D in x is the compound type consisting of all the base classes in L(C) that succeed D.
This is needed to define the base constructor with no-parameters.
3) As per answer (2), it's needed to define the base constructor
I get the coding in that you basically provide an "object SomeClass" and a "class SomeClass" and the companion class is the class declaration and the object is a singleton. Of which you cannot create an instance. So... my question is mostly the purpose of a singleton object in this particular instance.
Is this basically just a way to provide class methods in Scala? Like + based methods in Objective-C?
I'm reading the Programming in Scala book and Chapter 4 just talked about singleton objects, but it doesn't get into a lot of detail on why this matters.
I realize I may be getting ahead of myself here and that it might be explained in greater detail later. If so, let me know. This book is reasonably good so far, but it has a lot of "in Java, you do this", but I have so little Java experience that I sort of miss a bit of the points I fear. I don't want this to be one of those situations.
I don't recall reading anywhere on the Programming in Scala website that Java was a prerequisite for reading this book...
Yes, companion singletons provide an equivalent to Java's (and C++'s, c#'s, etc.) static methods.
(indeed, companion object methods are exposed via "static forwarders" for the sake of Java interop)
However, singletons go a fair way beyond this.
A singleton can inherit methods from other classes/traits, which can't be done with statics.
A singleton can be passed as a parameter (perhaps via an inherited interface)
A singleton can exist within the scope of a surrounding class or method, just as Java can have inner classes
It's also worth noting that a singleton doesn't have to be a companion, it's perfectly valid to define a singleton without also defining a companion class.
Which helps make Scala a far more object-oriented language that Java (static methods don't belong to an object). Ironic, given that it's largely discussed in terms of its functional credentials.
In many cases we need a singleton to stand for unique object in our software system.
Think about the the solar system. We may have following classes
class Planet
object Earth extends Planet
object Sun extends Planet
object is a simple way to create singleton, of course it is usually used to create class level method, as static method in java
Additional to the given answers (and going in the same general direction as jilen), objects play an important role in Scala's implicit mechanism, e.g. allowing type-class-like behavior (as known from Haskell):
trait Monoid[T] {
def zero:T
def sum(t1:T, t2:T):T
}
def fold[T](ts:T*)(implicit m:Monoid[T]) = ts.foldLeft(m.zero)(m.sum(_,_))
Now we have a fold-Function. which "collapses" a number of Ts together, as long as there is an appropriate Monoid (things that have a neutral element, and can be "added" somehow together) for T. In order to use this, we need only one instance of a Monoid for some type T, the perfect job for an object:
implicit object StringMonoid extends Monoid[String] {
def zero = ""
def sum(s1:String, s2:String) = s1 + s2
}
Now this works:
println(fold("a","bc","def")) //--> abcdef
So objects are very useful in their own right.
But wait, there is more! Companion objects can also serve as a kind of "default configuration" when extending their companion class:
trait Config {
def databaseName:String
def userName:String
def password:String
}
object Config extends Config {
def databaseName = "testDB"
def userName = "scott"
def password = "tiger"
}
So on the one hand you have the trait Config, which can be implemented by the user however she wants, but on the other hand there is a ready made object Config when you want to go with the default settings.
Yes, it is basically a way of providing class methods when used as a companion object.
In Programming in Scala: A Comprehensive Step-by-Step Guide, the author said:
One way in which Scala is more
object-oriented than Java is that
classes in Scala cannot have static
members. Instead, Scala has singleton
objects.
Why is a singleton object more object-oriented? What's the good of not using static members, but singleton objects?
Trying for the "big picture"; most of this has been covered in other answers, but there doesn't seem to be a single comprehensive reply that puts it all together and joins the dots. So here goes...
Static methods on a class are not methods on an object, this means that:
Static members can't be inherited from a parent class/trait
Static members can't be used to implement an interface
The static members of a class can't be passed as an argument to some function
(and because of the above points...)
Static members can't be overridden
Static members can't be polymorphic
The whole point of objects is that they can inherit from parent objects, implement interfaces, and be passed as arguments - static members have none of these properties, so they aren't truly object-oriented, they're little more than a namespace.
Singleton objects, on the other hand, are fully-fledged members of the object community.
Another very useful property of singletons is that they can easily be changed at some later point in time to not be singletons, this is a particularly painful refactoring if you start from static methods.
Imagine you designed a program for printing addresses and represented interactions with the printer via static methods on some class, then later you want to be able to add a second printer and allow the user to chose which one they'll use... It wouldn't be a fun experience!
Singleton objects behave like classes in that they can extend/implement other types.
Can't do that in Java with just static classes -- it's pretty sugar over the Java singleton pattern with a getInstance that allows (at least) nicer namespaces/stable identifiers and hides the distinction.
Hint: it's called object-oriented programming.
Seriously.
Maybe I am missing something fundamentally important, but I don't see what the fuss is all about: objects are more object-oriented than non-objects because they are objects. Does that really need an explanation?
Note: Although it sure sounds that way, I am really not trying to sound smug here. I have looked at all the other answers and I found them terribly confusing. To me, it's kind of obvious that objects and methods are more object-oriented than namespaces and procedures (which is what static "methods" really are) by the very definition of "object-oriented".
An alternative to having singleton objects would be to make classes themselves objects, as e.g. Ruby, Python, Smalltalk, Newspeak do.
For static members, there is no object. The class really just is a namespace.
In a singleton, there is always at least one object.
In all honesty, it's splitting hairs.
It's more object oriented in the sense that given a Scala class, every method call is a method call on that object. In Java, the static methods don't interact with the object state.
In fact, given an object a of a class A with the static method m(), it's considered bad practice to call a.m(). Instead it's recommended to call A.m() (I believe Eclipse will give you a warning). Java static methods can't be overridden, they can just be hidden by another method:
class A {
public static void m() {
System.out.println("m from A");
}
}
public class B extends A {
public static void m() {
System.out.println("m from B");
}
public static void main(String[] args) {
A a = new B();
a.m();
}
}
What will a.m() print?
In Scala, you would stick the static methods in companion objects A and B and the intent would be clearer as you would refer explicitly to the companion A or B.
Adding the same example in Scala:
class A
object A {
def m() = println("m from A")
}
class B extends A
object B {
def m() = println("m from B")
def main(args: Array[String]) {
val a = new B
A.m() // cannot call a.m()
}
}
There is some difference that may be important in some scenarios. In Java you
can't override static method so if you had class with static methods you would not be able to customize and override part of its behavior. If you used singleton object, you could just plug singleton created from subclass.
It's a marketing thing, really. Consider two examples:
class foo
static const int bar = 42;
end class
class superfoo
Integer bar = ConstInteger.new(42);
end class
Now, what are the observable differences here?
in a well-behaved language, the additional storage created is the same.
Foo.bar and Superfoo.bar have exactly the same signatures, access, and so on.
Superfoo.bar may be allocated differently but that's an implementation detail
It reminds me of the religious wars 20 years ago over whether C++ or Java were "really" Object Oriented, since after all both exposed primitive types that aren't "really" objects -- so, for example you can't inherit from int but can from Integer.
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.