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

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.

Related

Abstract class and trait use case [duplicate]

What is the advantage of using an abstract class instead of a trait (apart from performance)? It seems like abstract classes can be replaced by traits in most cases.
I can think of two differences
Abstract classes can have constructor parameters as well as type parameters. Traits can have only type parameters. There was some discussion that in future even traits can have constructor parameters
Abstract classes are fully interoperable with Java. You can call them from Java code without any wrappers. Traits are fully interoperable only if they do not contain any implementation code
There's a section in Programming in Scala called "To trait, or not to trait?" which addresses this question. Since the 1st ed is available online, I'm hoping it's OK to quote the whole thing here. (Any serious Scala programmer should buy the book):
Whenever you implement a reusable collection of behavior, you will
have to decide whether you want to use a trait or an abstract class.
There is no firm rule, but this section contains a few guidelines to
consider.
If the behavior will not be reused, then make it a concrete class. It
is not reusable behavior after all.
If it might be reused in multiple, unrelated classes, make it a trait.
Only traits can be mixed into different parts of the class hierarchy.
If you want to inherit from it in Java code, use an abstract class.
Since traits with code do not have a close Java analog, it tends to be
awkward to inherit from a trait in a Java class. Inheriting from a
Scala class, meanwhile, is exactly like inheriting from a Java class.
As one exception, a Scala trait with only abstract members translates
directly to a Java interface, so you should feel free to define such
traits even if you expect Java code to inherit from it. See Chapter 29
for more information on working with Java and Scala together.
If you plan to distribute it in compiled form, and you expect outside
groups to write classes inheriting from it, you might lean towards
using an abstract class. The issue is that when a trait gains or loses
a member, any classes that inherit from it must be recompiled, even if
they have not changed. If outside clients will only call into the
behavior, instead of inheriting from it, then using a trait is fine.
If efficiency is very important, lean towards using a class. Most Java
runtimes make a virtual method invocation of a class member a faster
operation than an interface method invocation. Traits get compiled to
interfaces and therefore may pay a slight performance overhead.
However, you should make this choice only if you know that the trait
in question constitutes a performance bottleneck and have evidence
that using a class instead actually solves the problem.
If you still do not know, after considering the above, then start by
making it as a trait. You can always change it later, and in general
using a trait keeps more options open.
As #Mushtaq Ahmed mentioned, a trait cannot have any parameters passed to the primary constructor of a class.
Another difference is the treatment of super.
The other difference between classes and traits is that whereas in classes, super calls are statically bound, in traits, they are dynamically bound. If you write super.toString in a class, you know exactly which method implementation will be invoked. When you write the same thing in a trait, however, the method implementation to invoke for the super call is undefined when you define the trait.
See the rest of Chapter 12 for more details.
Edit 1 (2013):
There is a subtle difference in the way abstract classes behaves compared to traits. One of the linearization rules is that it preserves the inheritance hierarchy of the classes, which tends to push abstract classes later in the chain while traits can happily be mixed in. In certain circumstances, it's actually preferable to be in latter position of the class linearization, so abstract classes could be used for that. See constraining class linearization (mixin order) in Scala.
Edit 2 (2018):
As of Scala 2.12, trait's binary compatibility behavior has changed. Prior to 2.12, adding or removing a member to the trait required recompilation of all classes that inherit the trait, even if the classes have not changed. This is due to the way traits were encoded in JVM.
As of Scala 2.12, traits compile to Java interfaces, so the requirement has relaxed a bit. If the trait does any of the following, its subclasses still require recompilation:
defining fields (val or var, but a constant is ok – final val without result type)
calling super
initializer statements in the body
extending a class
relying on linearization to find implementations in the right supertrait
But if the trait does not, you can now update it without breaking binary compatibility.
For whatever it is worth, Odersky et al's Programming in Scala recommends that, when you doubt, you use traits. You can always change them into abstract classes later on if needed.
Other than the fact that you cannot directly extend multiple abstract classes, but you can mixin multiple traits into a class, it's worth mentioning that traits are stackable, since super calls in a trait are dynamically bound (it is referring a class or trait mixed before current one).
From Thomas's answer in Difference between Abstract Class and Trait:
trait A{
def a = 1
}
trait X extends A{
override def a = {
println("X")
super.a
}
}
trait Y extends A{
override def a = {
println("Y")
super.a
}
}
scala> val xy = new AnyRef with X with Y
xy: java.lang.Object with X with Y = $anon$1#6e9b6a
scala> xy.a
Y
X
res0: Int = 1
scala> val yx = new AnyRef with Y with X
yx: java.lang.Object with Y with X = $anon$1#188c838
scala> yx.a
X
Y
res1: Int = 1
When extending an abstract class, this shows that the subclass is of a similar kind. This is not neccessarily the case when using traits, I think.
In Programming Scala the authors say that abstract classes make a classical object oriented "is-a" relationship while traits are a scala-way of composition.
Abstract classes can contain behaviour - They can parameterized with constructor args (which traits can't) and represent a working entity. Traits instead just represent a single feature, an interface of one functionality.
A class can inherit from multiple traits but only one abstract class.
Abstract classes can have constructor parameters as well as type parameters. Traits can have only type parameters. For example, you can’t say trait t(i: Int) { }; the i parameter is illegal.
Abstract classes are fully interoperable with Java. You can call them from Java code without any wrappers. Traits are fully interoperable only if they do not contain any implementation code.

why I can update state of an Object extend immutable trait in scala

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.

Why do we need traits in scala?

So, I was trying to make a finagle server, talk to sentry (not important), and stumbled upon a case, where I needed to inherit from two classes (not traits) at the same time, let's call them class SentryHandler extends Handler and class TwitterHandler extends Handler, and assume, that I need to create MyHandler, that inherits from both of them.
After a moment of stupidity, when I thought it was impossible without using a dreaded "delegation pattern", I found a solution:
trait SentryTrait extends SentryHandler
class MyHandler extends TwitterHandler with SentryTrait
Now, this got me thinking: what is the purpose of having the notion of "trait" to being with? If the idea was to enforce that you can inherit from multiple traits but only a single class, it seems awfully easy to get around. It kinda sounds like class is supposed to be the "main" line of inheritance (that you "extend a class with traits", but that isn't true either: you can extend a trait with (or without) a bunch of other traits, and no class at all.
You cannot instantiate a trait, but the same holds for an abstract class ...
The only real difference I can think of is that a trait cannot have constructor parameters. But what is the significance of that?
I mean, why not? What would the problem with something like this?
class Foo(bar: String, baz: String) extends Bar(bar) with Baz(baz)
Your solution (if I understood correctly) - doesn't work. You cannot multiinherit classes in scala:
scala> class Handler
defined class Handler
scala> class SentryHandler extends Handler
defined class SentryHandler
scala> class TwitterHandler extends Handler
defined class TwitterHandler
scala> trait SentryTrait extends SentryHandler
defined trait SentryTrait
scala> class MyHandler extends TwitterHandler with SentryTrait
<console>:11: error: illegal inheritance; superclass TwitterHandler
is not a subclass of the superclass SentryHandler
of the mixin trait SentryTrait
class MyHandler extends TwitterHandler with SentryTrait
As for the question - why traits, as I see it, this is because traits are stackable in order to solve the famous diamond problem
trait Base { def x: Unit = () }
trait A extends Base { override def x: Unit = { println("A"); super.x}}
trait B extends Base { override def x: Unit = { println("B"); super.x}}
class T1 extends A with B {}
class T2 extends B with A {}
(new T1).x // Outputs B then A
(new T2).x // Outputs A then B
Even though trait A super is Base (for T1) it calls B implementation rather then Base. This is due to trait linearization
So for classes if you extend something - you can be sure that this base will be called next. But this is not true for traits. And that's probably why you do not have trait constructor parameters
The question should rather be: why do we need classes in Scala? Martin Odersky has said that Scala could get by with just traits. We would need to add constructors to traits, so that instances of traits can be constructed. That's okay, Odersky has said that he has worked out a linearization algorithm for trait constructors.
The real purpose is platform interoperability.
Several of the platforms Scala intends to integrate with (currently Java, formerly .NET, maybe in the future Cocoa/Core Foundation/Swift/Objective-C) have a distinct notion of classes, and it is not always easy to have a 1:1 mapping between Scala traits and platform classes. This is different, for example, from interfaces: there is a trivial mapping between platform interfaces and Scala traits – a trait with only abstract members is isomorphic to an interface.
Classes, packages, and null are some examples of Scala features whose main purpose is platform integration.
The Scala designers try very hard to keep the language small, simple, and orthogonal. But Scala is also explicitly intended to integrate well with existing platforms. In fact, even though Scala is a fine language in itself, it was specifically designed as a replacement for the major platform languages (Java on the Java platform, C# on the .NET platform). And in order to do that, some compromises have to be made:
Scala has classes, even though they are redundant with traits (assuming we add constructors to traits), because it's easy to map Scala classes to platform classes and almost impossible to map traits to platform classes. Just look at the hoops Scala has to jump through to compile traits to efficient JVM bytecode. (For every trait there is an interface which contains the API and a static class which contains the methods. For every class the trait is mixed into, a forwarder class is generated that forwards the method calls to trait methods to the static class belonging to that trait.)
Scala has packages, even though they are redundant with objects. Scala packages can be trivially mapped to Java packages and .NET namespaces. Objects can't.
Package Objects are a way to overcome some of the limitations of packages, if we didn't have packages, we wouldn't need package objects.
Type Erasure. It is perfectly possible to keep generic types around when compiling to the JVM, e.g. you could store them in annotations. But third-party Java libraries will have their types erased anyway, and other languages won't understand the annotations and treat Scala types as erased, too, so you have to deal with Type Erasure anyway, and if you have to do it anyway, then why do both?
null, of course. It is just not possible to automatically map between null and Option in any sane way, when interoperating with real-world Java code. You have to have null in Scala, even though we rather wished it weren't there.
The problem with having constructors and state in a trait (which then makes it a class) is with multiple inheritance. While this is technically possible in a hypothetical language, it is terrible for language definition and for understanding the program code. The diamond problem, mentioned in other responses to this question), causes the highest level base class constructor to be called twice (the constructor of A in the example below).
Consider this code in a Scala-like language that allows multiple inheritance:
Class A(val x: Int)
class B extends A(1)
class C extends A(2)
class D extends B, C
If state is included, then you have to have two copies of the value x in class A. So you have two copies of class A (or one copy and the diamond problem - so called due to the diamond shape of the UML inheritance diagram).
Diamond Multiple Inheritance
The early versions of the C++ compiler (called C-Front) had lots of bugs with this and the compiler or the compiled code often crashed handling them. Issues include if you have a reference to B or C, how do you (the compiler, actually) determine the start of the object? The compiler needs to know that in order to cast the object from the Base type (in the image below, or A in the image above) to the Descendant type (D in the image above).
Multiple Inheritance Memory Layout
But, does this apply to traits? The way I understand it, Traits are an easy way to implement composition using the Delegation Pattern (I assume you all know the GoF patterns). When we implement Delegation in any other language (Java, C++, C#), we keep a reference to the other object and delegate a message to it by calling the method in its class. If traits are implemented in Scala internally by simply keeping a reference and calling its method, then traits do exactly the same thing as Delegation. So, why can't it have a constructor? I think it should be able to have one without violating its intent.
The only real difference I can think of is that a trait cannot have constructor parameters. But what is the significance of that? I mean, why not?
Consider
trait A(val x: Int)
trait B extends A(1)
trait C extends A(2)
class D extends B with C
What should (new D {}).x be? Note: there are plans to add trait parameters in Scala 3, but still with restrictions, so that the above is not allowed.

How to (properly) enrich the standard library?

I would like to define an implicit conversion from Iterator[T] to a class that I have defined: ProactiveIterator[A].
The question isn't really how to do it but how to do it properly, i.e. where to place the method, so that it is as transparent and unobtrusive as possible. Ideally it should be as the implicit conversion from String to StringOps in scala.Predef If the conversion was from a class in the library to some other class, then it could be defined inside that class, but AFAIK that's not possible here.
So far I have considered to add an object containing these conversions, similarly to JavaConversions, but better options may be possible.
You don't really have much of a choice. All implicits must be contained within some sort of object, and imported with a wildcard import (you could import them individually, but I doubt you want that).
So you'll have some sort of implicits object:
package foo.bar
object Implicits {
implicit class ProactiveIterator[A](i: Iterator[A]) {
...
}
}
Then you must explicitly import it wherever you use it:
import foo.bar.Implicits._
In my opinion, this is a good thing. Someone reading the code might not understand where your pimped methods are coming from, so the explicit import is very helpful.
You can similarly place your implicits within a package object. You would have to import them the same way into other namespaces, but they would be available to classes within the same package.
For example, using the following, anything within foo.bar will have this implicit class available:
package foo
package object bar {
implicit class ProactiveIterator[A](i: Iterator[A]) {
...
}
}
Elsewhere you would import foo.bar._ (which may or may not be as clean, depending on what's in bar).

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