- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
How to force initialization of inner objects?
Thu, 2008-12-18, 15:36
Hello,
I'd like to have all inner objects created when their outer class is instanciated.
For example, if I have:
class Funny {
private var reg = List[AnyRef]()
object name extends AnyRef {
reg = this :: reg
}
def describe = {
reg mkString
}
}
Then I'd like " (new Funny) describe" to print the list of inner objects but since object are lazy initialized, the list is empty...
Is there any simple way to do that?
Thanks,
Sebastien
I'd like to have all inner objects created when their outer class is instanciated.
For example, if I have:
class Funny {
private var reg = List[AnyRef]()
object name extends AnyRef {
reg = this :: reg
}
def describe = {
reg mkString
}
}
Then I'd like " (new Funny) describe" to print the list of inner objects but since object are lazy initialized, the list is empty...
Is there any simple way to do that?
Thanks,
Sebastien
Thu, 2008-12-18, 15:57
#2
Re: How to force initialization of inner objects?
just reference the object "name" in the constructor of Funny.
On Thu, Dec 18, 2008 at 15:32, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:
On Thu, Dec 18, 2008 at 15:32, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:
Hello,name
I'd like to have all inner objects created when their outer class is instanciated.
For example, if I have:
class Funny {
private var reg = List[AnyRef]()
object name extends AnyRef {
reg = this :: reg
}
def describe = {
reg mkString
}
}
Then I'd like " (new Funny) describe" to print the list of inner objects but since object are lazy initialized, the list is empty...
Is there any simple way to do that?
Thanks,
Sebastien
Thu, 2008-12-18, 16:17
#3
Re: How to force initialization of inner objects?
Thanks, but it is not exactly what I want. I'm looking for scala.swing like functionality such that when I call "describe", I get the object names for free. An quick but ugly way is this:
class Funny {
private var reg = List[String]()
object name {
reg = this.getClass.getSimpleName :: reg
};name
def describe = {
reg mkString // returns Funny$name
}
}
Now, I'm investigating if I can make Funny inherit from a trait that uses reflection to initialize the inner objects, not sure if it'll work...
class Funny {
private var reg = List[String]()
object name {
reg = this.getClass.getSimpleName :: reg
};name
def describe = {
reg mkString // returns Funny$name
}
}
Now, I'm investigating if I can make Funny inherit from a trait that uses reflection to initialize the inner objects, not sure if it'll work...
Thu, 2008-12-18, 17:17
#4
Re: How to force initialization of inner objects?
On Thu, Dec 18, 2008 at 7:06 AM, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:
Run "javap -private Funny" to see the inner object member references, you'll see something like this if I remember correctly:
private Funny$name$ name$module;
and just referencing the class though reflection (Class.forName) I believe was enough to trigger initialization.
alex
Now, I'm investigating if I can make Funny inherit from a trait that uses reflection to initialize the inner objects, not sure if it'll work...
Run "javap -private Funny" to see the inner object member references, you'll see something like this if I remember correctly:
private Funny$name$ name$module;
and just referencing the class though reflection (Class.forName) I believe was enough to trigger initialization.
alex
Thu, 2008-12-18, 17:27
#5
Re: How to force initialization of inner objects?
Thanks Lukas, it seems accessing manually the objects from the constructor is the easiest way :(
I thought naively that reflection would help but it does not initialize the fields, I'm getting null's on the console with the sample below.
trait InitObjects {
def init(a:AnyRef) {
for (f <- this.getClass.getDeclaredFields) {
f.setAccessible(true)
println(f.getType)
println(f.get(this))
}
}
}
class Funny extends InitObjects {
init(this)
private var reg = List[String]()
object name {
reg = this.getClass.getSimpleName :: reg
}
def describe = {
reg mkString
}
}
scala> new Funny
class line8$object$$iw$$iw$$iw$Funny$name$
null
class scala.List
null
res5: Funny = Funny@7afcba
Thanks the help,
Sebastien
2008/12/18 Lukas Rytz <lukas.rytz@epfl.ch>
I thought naively that reflection would help but it does not initialize the fields, I'm getting null's on the console with the sample below.
trait InitObjects {
def init(a:AnyRef) {
for (f <- this.getClass.getDeclaredFields) {
f.setAccessible(true)
println(f.getType)
println(f.get(this))
}
}
}
class Funny extends InitObjects {
init(this)
private var reg = List[String]()
object name {
reg = this.getClass.getSimpleName :: reg
}
def describe = {
reg mkString
}
}
scala> new Funny
class line8$object$$iw$$iw$$iw$Funny$name$
null
class scala.List
null
res5: Funny = Funny@7afcba
Thanks the help,
Sebastien
2008/12/18 Lukas Rytz <lukas.rytz@epfl.ch>
just reference the object "name" in the constructor of Funny.
On Thu, Dec 18, 2008 at 15:32, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:
Hello,name
I'd like to have all inner objects created when their outer class is instanciated.
For example, if I have:
class Funny {
private var reg = List[AnyRef]()
object name extends AnyRef {
reg = this :: reg
}
def describe = {
reg mkString
}
}
Then I'd like " (new Funny) describe" to print the list of inner objects but since object are lazy initialized, the list is empty...
Is there any simple way to do that?
Thanks,
Sebastien
Thu, 2008-12-18, 19:27
#6
Re: How to force initialization of inner objects?
One thing I've done in the past is used reflection to find all vals matching a specific type. Then you can define a method which calls all of those reflectively and call that somewhere in the constructor. Initialization order issues mean that that call should probably still be manual though.
On Thu, Dec 18, 2008 at 11:04 AM, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:
On Thu, Dec 18, 2008 at 11:04 AM, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:
Thanks Lukas, it seems accessing manually the objects from the constructor is the easiest way :(
I thought naively that reflection would help but it does not initialize the fields, I'm getting null's on the console with the sample below.
trait InitObjects {
def init(a:AnyRef) {
for (f <- this.getClass.getDeclaredFields) {
f.setAccessible(true)
println(f.getType)
println(f.get(this))
}
}
}
class Funny extends InitObjects {
init(this)
private var reg = List[String]()
object name {
reg = this.getClass.getSimpleName :: reg
}
def describe = {
reg mkString
}
}
scala> new Funny
class line8$object$$iw$$iw$$iw$Funny$name$
null
class scala.List
null
res5: Funny = Funny@7afcba
Thanks the help,
Sebastien
2008/12/18 Lukas Rytz <lukas.rytz@epfl.ch>
just reference the object "name" in the constructor of Funny.
On Thu, Dec 18, 2008 at 15:32, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:
Hello,name
I'd like to have all inner objects created when their outer class is instanciated.
For example, if I have:
class Funny {
private var reg = List[AnyRef]()
object name extends AnyRef {
reg = this :: reg
}
def describe = {
reg mkString
}
}
Then I'd like " (new Funny) describe" to print the list of inner objects but since object are lazy initialized, the list is empty...
Is there any simple way to do that?
Thanks,
Sebastien
Fri, 2008-12-19, 11:37
#7
Re: How to force initialization of inner objects?
Thanks you all for the advice, it works now. javap shows that the field corresponding to the inner object is initialized with a new instance of Funny$name in the name() method is invoked. Therefore I used reflection to invoke all the methods that return a specific type inherited by my inner objects like in the sample below.
trait EarlyBird {
for (f <- this.getClass.getDeclaredMethods) {
if (f.getParameterTypes().length == 0 && classOf[Var].isAssignableFrom(f.getReturnType())) {
f.invoke(this)
}
}
}
object Registry {
var l = List[String]()
}
abstract class Var {
Registry.l = this.getClass.getSimpleName :: Registry.l
}
class Funny extends EarlyBird {
object name extends Var
}
// scala> new Funny
// scala> Registry.l.mkString
// res1: String = Funny$name$
This works but there is one last thing worrying me, is it safe to assume that this pattern won't break with new releases of Scala?
Thanks,
Sebastien
trait EarlyBird {
for (f <- this.getClass.getDeclaredMethods) {
if (f.getParameterTypes().length == 0 && classOf[Var].isAssignableFrom(f.getReturnType())) {
f.invoke(this)
}
}
}
object Registry {
var l = List[String]()
}
abstract class Var {
Registry.l = this.getClass.getSimpleName :: Registry.l
}
class Funny extends EarlyBird {
object name extends Var
}
// scala> new Funny
// scala> Registry.l.mkString
// res1: String = Funny$name$
This works but there is one last thing worrying me, is it safe to assume that this pattern won't break with new releases of Scala?
Thanks,
Sebastien
2008/12/18 David MacIver <david.maciver@gmail.com>
One thing I've done in the past is used reflection to find all vals matching a specific type. Then you can define a method which calls all of those reflectively and call that somewhere in the constructor. Initialization order issues mean that that call should probably still be manual though.
On Thu, Dec 18, 2008 at 11:04 AM, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:Thanks Lukas, it seems accessing manually the objects from the constructor is the easiest way :(
I thought naively that reflection would help but it does not initialize the fields, I'm getting null's on the console with the sample below.
trait InitObjects {
def init(a:AnyRef) {
for (f <- this.getClass.getDeclaredFields) {
f.setAccessible(true)
println(f.getType)
println(f.get(this))
}
}
}
class Funny extends InitObjects {
init(this)reg = this.getClass.getSimpleName :: reg
private var reg = List[String]()
object name {
}
def describe = {
reg mkString
}
}
scala> new Funny
class line8$object$$iw$$iw$$iw$Funny$name$
null
class scala.List
null
res5: Funny = Funny@7afcba
Thanks the help,
Sebastien2008/12/18 Lukas Rytz <lukas.rytz@epfl.ch>
just reference the object "name" in the constructor of Funny.On Thu, Dec 18, 2008 at 15:32, Sebastien Bocq <sebastien.bocq@gmail.com> wrote:
Hello,
I'd like to have all inner objects created when their outer class is instanciated.
For example, if I have:
class Funny {
private var reg = List[AnyRef]()
name
object name extends AnyRef {
reg = this :: reg
}
def describe = {
reg mkString
}
}
Then I'd like " (new Funny) describe" to print the list of inner objects but since object are lazy initialized, the list is empty...
Is there any simple way to do that?
Thanks,
Sebastien
Fri, 2008-12-19, 14:57
#8
Re: How to force initialization of inner objects?
On Fri, Dec 19, 2008 at 11:21 AM, Sebastien Bocq
<sebastien.bocq@gmail.com> wrote:
> Thanks you all for the advice, it works now. javap shows that the field
> corresponding to the inner object is initialized with a new instance of
> Funny$name in the name() method is invoked. Therefore I used reflection to
> invoke all the methods that return a specific type inherited by my inner
> objects like in the sample below.
>
> trait EarlyBird {
> for (f <- this.getClass.getDeclaredMethods) {
> if (f.getParameterTypes().length == 0 &&
> classOf[Var].isAssignableFrom(f.getReturnType())) {
> f.invoke(this)
> }
> }
> }
>
> object Registry {
> var l = List[String]()
> }
>
> abstract class Var {
> Registry.l = this.getClass.getSimpleName :: Registry.l
> }
>
> class Funny extends EarlyBird {
>
> object name extends Var
>
> }
>
> // scala> new Funny
> // scala> Registry.l.mkString
> // res1: String = Funny$name$
>
> This works but there is one last thing worrying me, is it safe to assume
> that this pattern won't break with new releases of Scala?
Hard to say. Scala has many features that are difficult to translate
to the JVM, and specifying the implementation details would be too
limiting and make things even harder. The Scala Language Specification
says that an object definition is 'roughly equivalent' to a field and
an accessor method that instantiates the object on first access. Your
code seems to rely on the assumption that there's one method per
object that returns a subtype of 'Var', and that there are no other
methods with this signature. It will probably work with future
versions of Scala. But I don't know about future versions of your own
code :)
There are plans to reimplement objects in terms of lazy values. That
will change the way objects are represented in bytecode, although
there will still be an accessor method with the right name.
Cheers,
Iulian
>
> Thanks,
> Sebastien
>
private var reg = List[AnyRef]()
val name = new AnyRef {
reg = this.reg
}
def describe = {
reg mkString
}
}
On Thu, Dec 18, 2008 at 6:32 AM, Sebastien Bocq <sebastien.bocq@gmail.com> wrote: