- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
private constructor
Thu, 2009-03-19, 03:20
Example:
class Bla private (id: Int)
javap output:
public class Bla extends java.lang.Object implements scala.ScalaObject{
private Bla(int);
}
All good and fine.
Now if I add an companion object:
object Bla {
def construct(id: Int) = new Bla(id)
}
javap output:
public class Bla extends java.lang.Object implements scala.ScalaObject{
public static final Bla construct(int);
public Bla(int);
}
The constructor has become public. Why?
Secondarily, I was also surprised to see the companion method implemented as a static method on the class. Is that feature? I don't remember reading about that behavior anywhere, although I like it, for purposes of Java interop.
Thanks,
Nils
class Bla private (id: Int)
javap output:
public class Bla extends java.lang.Object implements scala.ScalaObject{
private Bla(int);
}
All good and fine.
Now if I add an companion object:
object Bla {
def construct(id: Int) = new Bla(id)
}
javap output:
public class Bla extends java.lang.Object implements scala.ScalaObject{
public static final Bla construct(int);
public Bla(int);
}
The constructor has become public. Why?
Secondarily, I was also surprised to see the companion method implemented as a static method on the class. Is that feature? I don't remember reading about that behavior anywhere, although I like it, for purposes of Java interop.
Thanks,
Nils
Thu, 2009-03-19, 04:07
#2
Re: private constructor
Nils Kilden-Pedersen wrote:
> Example:
>
> class Bla private (id: Int)
>
> javap output:
> public class Bla extends java.lang.Object implements scala.ScalaObject{
> private Bla(int);
> }
>
> All good and fine.
>
> Now if I add an companion object:
>
> object Bla {
> def construct(id: Int) = new Bla(id)
> }
>
> javap output:
> public class Bla extends java.lang.Object implements scala.ScalaObject{
> public static final Bla construct(int);
> public Bla(int);
> }
>
> The constructor has become public. Why?
It is only public in the bytecode, not to the Scala compiler. The Scala
compiler won't let other classes call the constructor. (Metadata is
added to the bytecode, telling the Scala compiler to treat the
constructor as private.)
The Scala language spec says that the companion object may access the
constructor, but the compiler compiles the companion object into a
separate class, so the constructor needs to be non-private in the
bytecode or the JVM would stop the companion object calling it.
(A compiler could instead have made it package-private or protected,
just not private.)
> Secondarily, I was also surprised to see the companion method
> implemented as a static method on the class. Is that feature? I don't
> remember reading about that behavior anywhere, although I like it, for
> purposes of Java interop.
Yes. A typical use case is your application's
def main(args: Array[String]): Unit
The language spec doesn't describe the translation, but the book
'Programming in Scala' does:
An important special case is if
you have a “standalone” singleton object, one which does not come with a
class of the same name. ... In that case, the compiler
will create a Java class ... that has a static forwarder method for
each method of the Scala singleton object
Thu, 2009-03-19, 04:17
#3
Re: private constructor
On Wed, Mar 18, 2009 at 09:20:40PM -0500, Nils Kilden-Pedersen wrote:
> The constructor has become public. Why?
I don't know the answer to that one yet, but I see it was also the case
in 2.7.x so we can all breathe a sigh of relief that I didn't break it.
> Secondarily, I was also surprised to see the companion method
> implemented as a static method on the class. Is that feature?
Yes, that is a recently implemented feature which may yet need a little
fine tuning so I'm glad to see it being test driven.
Thu, 2009-03-19, 04:27
#4
Re: Re: private constructor
On Wed, Mar 18, 2009 at 10:03 PM, Eric Willigers <ewilligers@gmail.com> wrote:
Yes, that makes sense, but since the companion object is in the same package (must be, correct?), it seems that package scope access would be more reasonable. That's what happens with inner classes in Java (through synthetics, IIRC).
Nils Kilden-Pedersen wrote:
The constructor has become public. Why?
the compiler compiles the companion object into a separate class, so the constructor needs to be non-private in the bytecode or the JVM would stop the companion object calling it.
Yes, that makes sense, but since the companion object is in the same package (must be, correct?), it seems that package scope access would be more reasonable. That's what happens with inner classes in Java (through synthetics, IIRC).
Thu, 2009-03-19, 15:17
#5
Re: Re: private constructor
On Wed, Mar 18, 2009 at 10:10 PM, Nils Kilden-Pedersen <nilskp@gmail.com> wrote:
In fact, wouldn't the proper thing to do, be to do exactly that? Leave the constructor private, but add a package protected synthetic constructor?
Yes, that makes sense, but since the companion object is in the same package (must be, correct?), it seems that package scope access would be more reasonable. That's what happens with inner classes in Java (through synthetics, IIRC).
In fact, wouldn't the proper thing to do, be to do exactly that? Leave the constructor private, but add a package protected synthetic constructor?
The static method though appears to be a 2.8 feature, since that was not available with 2.7.3.