When should I use package and when object in Scala? - scala

What is the difference between package and object?

Packages are not run-time entities, objects are. You should use packages to organize the hierarchy of your code, and objects whenever you need something to store code or data (assuming plain classes and instances are not better, of course).

To add a bit to Daniel's answer:
From the Scala specifications:
Objects
Classes (§5.3) and objects (§5.4) are both defined in terms of templates.
A template defines the type signature, behavior and initial state of a trait or class of objects or of a single object.
It can have:
local modifiers (‘abstract’, ‘final’, ‘sealed’, ‘implicit’, ‘lazy’)
access modified (‘private’ | ‘protected’),
access qualifier (‘this’)
An object definition defines a single object of a new class (or: module) conforming to the template t.
It is roughly equivalent to the following three definitions, which together
define a class and create a single object of that class on demand:
final class m$cls extends t
private var m$instance = null
final def m = {
if (m$instance == null) m$instance = new m$cls
m$instance
}
An object can isolate a code common for other Class instances.. A specific usage:
Classes in Scala do not have static members; however, an equivalent effect can be achieved by an accompanying object definition.
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.
Packages
a package is part of compilation unit.
A compilation unit consists of a sequence of packagings, import clauses, and class
and object definitions, which may be preceded by a package clause.
A package is a special object which defines a set of member classes, objects and
packages.
Unlike other objects, packages may not be used as values. It is illegal to have a package with the same fully qualified name as a module or a class.
Top-level definitions outside a packaging are assumed to be injected into a special
empty package. That package cannot be named and therefore cannot be imported.
The special predefined name _root_ refers to the outermost root package which
contains all top-level packages.
So:
object organize code to be executed from a unique runtime instance.
package declare code namespace for the compilation step.

Related

Why does class name of a type in a package object contain "package" in runtime class name?

I'm trying to generate the runtime class name of a class that is defined in a package object.
Example:
package com.foo
package object bar {
case class MyCaseClass()
}
import bar._
MyCaseClass().getClass.getCanonicalName
The above will generate com.foo.bar.package.MyCaseClass
If I use WeakTypeTag it will correctly generate the type as com.foo.bar.MyCaseClass.
package com.foo
trait MyTrait
case class MyImpl extends MyTrait
def getType[T](t: T)(implicit weakTypeTag WeakTypeTag[T]): String = {
weakTypeTag.tpe.fullName
}
What is the reason for the above difference in behavior? I know I must be missing something about the Scala type system...
This isn't so much about the type system as about the encoding of package objects on the JVM. The JVM doesn't have package-level methods, for example, so the Scala compiler has to create a synthetic class that has static methods, inner classes, etc. corresponding to the definitions in the package object. That class is named package, an arbitrary but self-explanatory name that has the advantage of being a keyword in both Scala and Java, so it's unlikely to result in collisions with non-synthetic code.
Java's reflection APIs know nothing about Scala, so naturally they can't hide this encoding from you. When you call getClass.getCanonicalName you're seeing the actual class name, corresponding to the class file you'd find at com/foo/bar/package\$MyCaseClass.class when you compile your code.
Scala's reflection APIs do know about Scala's encoding of package objects, and they will hide the synthetic package class from you. This arguably makes sense, since the details of the encoding aren't in the spec (if I remember correctly?) and so may vary across platforms or language versions, etc.
The discrepancy is a little confusing, but this isn't the only time you'll run into differences—the Scala reflection API hides lots of mangling, etc. that Java reflection can't.

Scala newInstance() an inner class nested in a trait

I'm writing a script to automatically configure sharding for some specific MongoDB collections when the app is being deployed on a fresh cluster. The application is using the Lift framework and basically every sharded collection is mapped to a MongoRecord class extending a particular "ShardedCollection" trait. I need to call a particular method on those classes in order to get their collection name.
So the first step is to find in the code those specifics classes and for that I use ClassUtil . Then I need a way to instantiate them and for that I thought that java reflection should be able to do it. It's working but only if those classes do not belong to an outer class.
The configuration in this specific edge case is like:
class X {
class Y extends ShardedCollection {
}
}
So after reading some documentation I found that I had to call YConstructor.newInstance(XObject), newInstance taking as a first argument an XObject (as an instance of X) When Y is an inner class of X. My strategy is to recursively instantiate the enclosing classes until I'm getting the one that has the ShardedCollection trait.
The problem arise when X is no more a class but a trait, and then there is no constructor that I can use for it, but I still need to feed an XObject to newInstance .. Tricky :(
To be very concise from the java doc
If the constructor's declaring class is an inner class in a non-static context, the first argument to the constructor needs to be the enclosing instance
What do I do when the enclosing "thing" is a trait ? (assuming that I can't modify anything in the code base)

Why are classes inside Scala package objects dispreferred?

Starting with 2.10, -Xlint complains about classes defined inside of package objects. But why? Defining a class inside a package object should be exactly equivalent to defining the classes inside of a separate package with the same name, except a lot more convenient.
In my opinion, one of the serious design flaws in Scala is the inability to put anything other than a class-like entity (e.g. variable declarations, function definitions) at top level of a file. Instead, you're forced to put them into a separate ''package object'' (often in package.scala), separate from the rest of the code that they belong with and violating a basic programming rule which is that conceptually related code should be physically related as well. I don't see any reason why Scala can't conceptually allow anything at top level that it allows at lower levels, and anything non-class-like automatically gets placed into the package object, so that users never have to worry about it.
For example, in my case I have a util package, and under it I have a number of subpackages (util.io, util.text, util.time, util.os, util.math, util.distances, etc.) that group heterogeneous collections of functions, classes and sometimes variables that are semantically related. I currently store all the various functions, classes, etc. in a package object sitting in a file called io.scala or text.scala or whatever, in the util directory. This works great and it's very convenient because of the way functions and classes can be mixed, e.g. I can do something like:
package object math {
// Coordinates on a sphere
case class SphereCoord(lat: Double, long: Double) { ... }
// great-circle distance between two points
def spheredist(a: SphereCoord, b: SphereCoord) = ...
// Area of rectangle running along latitude/longitude lines
def rectArea(topleft: SphereCoord, botright: SphereCoord) = ...
// ...
// ...
// Exact-decimal functions
class DecimalInexactError extends Exception
// Format floating point value in decimal, error if can't do exactly
formatDecimalExactly(val num: Double) = ...
// ...
// ...
}
Without this, I would have to split the code up inconveniently according to fun vs. class rather than by semantics. The alternative, I suppose, is to put them in a normal object -- kind of defeating the purpose of having package objects in the first place.
But why? Defining a class inside a package object should be exactly equivalent to defining the classes inside of a separate package with the same name,
Precisely. The semantics are (currently) the same, so if you favor defining a class inside a package object, there should be a good reason. But the reality is that there is at least one good reason no to (keep reading).
except a lot more convenient
How is that more convenient?
If you are doing this:
package object mypkg {
class MyClass
}
You can just as well do the following:
package mypkg {
class MyClass
}
You'll even save a few characters in the process :)
Now, a good and concrete reason not to go overboard with package objects is that while packages are open, package objects are not.
A common scenario would be to have your code dispatched among several projects, with each project defining classes in the same package. No problem here.
On the other hand, a package object is (like any object) closed (as the spec puts it "There can be only one package object per package"). In other words,
you will only be able to define a package object in one of your projects.
If you attempt to define a package object for the same package in two distinct projects, bad things will happen, as you will effectively end up with two
distinct versions of the same JVM class (n our case you would end up with two "mypkg.class" files).
Depending on the cases you might end up with the compiler complaining that it cannot find something that you defined in the first version of your package object,
or get a "bad symbolic reference" error, or potentially even a runtime error. This is a general limitation of package objects, so you have to be aware of it.
In the case of defining classes inside a package object, the solution is simple: don't do it (given that you won't gain anything substantial compared to just defining the class as a top level).
For type aliase, vals and vars, we don't have such a luxuary, so in this case it is a matter of weighing whether the syntactic convenience (compared to defining them in an object) is worth it, and then take care not to define duplicate package objects.
I have not found a good answer to why this semantically equivalent operation would generate a lint warning. Methinks this is a lint bug. The only thing that I have found that must not be placed inside a package object (vs inside a plain package) is an object that implements main (or extends App).
Note that -Xlint also complains about implicit classes declared inside package objects, even though they cannot be declared at package scope. (See http://docs.scala-lang.org/overviews/core/implicit-classes.html for the rules on implicit classes.)
I figured out a trick that allows for all the benefits of package objects without the complaints about deprecation. In place of
package object foo {
...
}
you can do
protected class FooPackage {
...
}
package object foo extends FooPackage { }
Works the same but no complaint. Clear sign that the complaint itself is bogus.

Private scoping with square brackets (private[...]) in Scala

I've come across the following syntax while looking through the Gatling source code:
private[http] def build = {
// ...
}
What is the syntax inside square brackets?
When I click through it in my IDE it is an alias to a fully qualified package (com.excilys.ebi.gatling.http) but I can't find where that alias was defined.
See the scala reference, specifically, chapter 5.2. Some excerpt:
The private modifier can be used with any definition or declaration in a template. Such members can be accessed only from within the directly enclosing template and its companion module or companion class (§5.4). They are
not inherited by subclasses and they may not override definitions in parent
classes.
The modifier can be qualified with an identifier C (e.g. private[C]) that must
denote a class or package enclosing the definition. Members labeled with
such a modifier are accessible respectively only from code inside the package C or only from code inside the class C and its companion module (§5.4).
Such members are also inherited only from templates inside C.
In short: this is used for scope protection:
private[C] means that access is private "up to" C, where C is the
corresponding package, class or singleton object.
Same to protected[C]
protected[C]: access is protected "up to" C, where C is the
corresponding package, class or singleton object.

Why is a defined object called 'module' by the Scala interpreter?

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, ...)