This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Scala and (non-)nested classes question

7 replies
Silvio Bierman
Joined: 2009-02-16,
User offline. Last seen 1 year 16 weeks ago.

Hello all,

First of all I want to say I am relatively new to Scala (but a Java and
before that C++ old-timer).

I am trying to recreate a Scala version of a utility framework that I once
wrote in Java. Naturally I want to fully benefit from Scala powers so I am
trying not to write Java code in Scala syntax.

In the Java version the was a large class hierarchy with many (user) classes
directly or indirectly extending abstract class BaseNode. XNode objects
could be combined into multiple trees (parent-child hierarchy). However, all
related XNode objects needed to register themselves with a NodeRegistry.
Since XNode classes would typically instanciate other YNode classes in their
constructors there was a lot of passing around of the NodeRegistry instance.

Initially in Java I tried to do this:

/* NodeRegsitry.java */
class NodeRegistry
{
public abstract class BaseNode { }
}

/*MyNode.java */
class MyNode extends NodeRegistry.BaseNode
{
}

iow. have all XNode classes extend NodeRegsitry.BaseNode. Of course Java did
not allow extending BaseNode outside of the NodeRegistry class. My intention
was to get the implicit NodeRegistry instance passed along implicitly by
creating XNode instances only inside other XNode members where the
NodeRegistry instance was known. If one would have to be created elsewhere I
would then use nodeRegistryInstance.new SomeNode().

Since that was impossible I reverted to demanding the NodeRegistry instance
in the BaseNode constructor.

I do not know if my story makes any sense but I guess what I am looking for
is a way to have classes and their instances in some class herarchy share
some common registry/context instance without explicitly passing it around.

Is there a way to do this in Scala?

Thanks in advance for any suggestions.

Silvio

Colin Bullock
Joined: 2009-01-23,
User offline. Last seen 42 years 45 weeks ago.
Re: Scala and (non-)nested classes question
One potential solution:

class NodeRegistry
class BaseNode(val reg: NodeRegistry)

trait NodeRegistryComponent {
  def registry: NodeRegistry
}

trait Nodes {
  self: NodeRegistryComponent =>
 
  class XNode extends BaseNode(registry)
  class YNode extends BaseNode(registry)
  // ...
}

object nodes extends Nodes with NodeRegistryComponent {
  override val registry = new NodeRegistry
}

scala> import nodes._
import nodes._

scala> val x = new XNode
x: nodes.XNode = Nodes$XNode@7f59c7

scala> val y = new YNode
y: nodes.YNode = Nodes$YNode@247bd2

scala> x.reg
res0: NodeRegistry = NodeRegistry@b72911

scala> y.reg
res1: NodeRegistry = NodeRegistry@b72911

scala>

- Colin
Silvio Bierman
Joined: 2009-02-16,
User offline. Last seen 1 year 16 weeks ago.
Re: Scala and (non-)nested classes question

Colin Bullock wrote:
>
> One potential solution:
>
> class NodeRegistry
> class BaseNode(val reg: NodeRegistry)
>
> trait NodeRegistryComponent {
> def registry: NodeRegistry
> }
>
> trait Nodes {
> self: NodeRegistryComponent =>
>
> class XNode extends BaseNode(registry)
> class YNode extends BaseNode(registry)
> // ...
> }
>
> object nodes extends Nodes with NodeRegistryComponent {
> override val registry = new NodeRegistry
> }
>
> scala> import nodes._
> import nodes._
>
> scala> val x = new XNode
> x: nodes.XNode = Nodes$XNode@7f59c7
>
> scala> val y = new YNode
> y: nodes.YNode = Nodes$YNode@247bd2
>
> scala> x.reg
> res0: NodeRegistry = NodeRegistry@b72911
>
> scala> y.reg
> res1: NodeRegistry = NodeRegistry@b72911
>
> scala>
>
> - Colin
>
>

But that will mean I have to define all my XNode classes inside trait Nodes,
doesn't it? In the Java example I could have done this insode the
NodeRegsitry class. But as I understand it, traits, just like Java classes,
are not 'open' like packages (or a better example: C++ namespaces) are in
that you can add to them from multiple source files.

My problem is that a number of core classes is inside the framework but in
application code many classes will be derived (extended) from these classes.
Therefore, I need an open construction.

Since Node instances will only be created inside methods of already existing
Node instances I would like some implicit instance passing, just like with
nested classes in Java, but then extended accross multiple source files.

The Java limitation that a top-level class can not extend a nested class is
imho. a language choice. It would have been possible to allow this,
demanding that such top level classes could only be instantiated inside the
scope of an instance of the surrounding class of the base. I was hoping that
Scala would allow me to do this.

Still looking for a solution.

gdefacci
Joined: 2008-08-21,
User offline. Last seen 2 years 38 weeks ago.
Re: Scala and (non-)nested classes question

>> The Java limitation that a top-level class can not extend a nested class is
>> imho. a language choice.

// compilation unit SuperContainer

public class SupContainer {

public static class Sup {

}
}

// compilation unit Sub

public class Sub extends SupContainer.Sup {

}

In java top level classes can extend inner classes. Top level classes
cant extend non static inner classes, since non static inner classes
can access members of the class in which they are defined.

best regards

G

On 2/18/09, Silvio Bierman wrote:
>
>
>
> Colin Bullock wrote:
>>
>> One potential solution:
>>
>> class NodeRegistry
>> class BaseNode(val reg: NodeRegistry)
>>
>> trait NodeRegistryComponent {
>> def registry: NodeRegistry
>> }
>>
>> trait Nodes {
>> self: NodeRegistryComponent =>
>>
>> class XNode extends BaseNode(registry)
>> class YNode extends BaseNode(registry)
>> // ...
>> }
>>
>> object nodes extends Nodes with NodeRegistryComponent {
>> override val registry = new NodeRegistry
>> }
>>
>> scala> import nodes._
>> import nodes._
>>
>> scala> val x = new XNode
>> x: nodes.XNode = Nodes$XNode@7f59c7
>>
>> scala> val y = new YNode
>> y: nodes.YNode = Nodes$YNode@247bd2
>>
>> scala> x.reg
>> res0: NodeRegistry = NodeRegistry@b72911
>>
>> scala> y.reg
>> res1: NodeRegistry = NodeRegistry@b72911
>>
>> scala>
>>
>> - Colin
>>
>>
>
> But that will mean I have to define all my XNode classes inside trait Nodes,
> doesn't it? In the Java example I could have done this insode the
> NodeRegsitry class. But as I understand it, traits, just like Java classes,
> are not 'open' like packages (or a better example: C++ namespaces) are in
> that you can add to them from multiple source files.
>
> My problem is that a number of core classes is inside the framework but in
> application code many classes will be derived (extended) from these classes.
> Therefore, I need an open construction.
>
> Since Node instances will only be created inside methods of already existing
> Node instances I would like some implicit instance passing, just like with
> nested classes in Java, but then extended accross multiple source files.
>
> The Java limitation that a top-level class can not extend a nested class is
> imho. a language choice. It would have been possible to allow this,
> demanding that such top level classes could only be instantiated inside the
> scope of an instance of the surrounding class of the base. I was hoping that
> Scala would allow me to do this.
>
> Still looking for a solution.
>
> --
> View this message in context:
> http://www.nabble.com/Scala-and-%28non-%29nested-classes-question-tp2208...
> Sent from the Scala - User mailing list archive at Nabble.com.
>
>

Silvio Bierman
Joined: 2009-02-16,
User offline. Last seen 1 year 16 weeks ago.
Re: Scala and (non-)nested classes question

Giovanni De Facci wrote:
>
>>> The Java limitation that a top-level class can not extend a nested class
>>> is
>>> imho. a language choice.
>
> // compilation unit SuperContainer
>
> public class SupContainer {
>
> public static class Sup {
>
> }
> }
>
> // compilation unit Sub
>
> public class Sub extends SupContainer.Sup {
>
> }
>
> In java top level classes can extend inner classes. Top level classes
> cant extend non static inner classes, since non static inner classes
> can access members of the class in which they are defined.
>
> best regards
>
> G
>
> On 2/18/09, Silvio Bierman wrote:
>>
>>
>>
>> Colin Bullock wrote:
>>>
>>> One potential solution:
>>>
>>> class NodeRegistry
>>> class BaseNode(val reg: NodeRegistry)
>>>
>>> trait NodeRegistryComponent {
>>> def registry: NodeRegistry
>>> }
>>>
>>> trait Nodes {
>>> self: NodeRegistryComponent =>
>>>
>>> class XNode extends BaseNode(registry)
>>> class YNode extends BaseNode(registry)
>>> // ...
>>> }
>>>
>>> object nodes extends Nodes with NodeRegistryComponent {
>>> override val registry = new NodeRegistry
>>> }
>>>
>>> scala> import nodes._
>>> import nodes._
>>>
>>> scala> val x = new XNode
>>> x: nodes.XNode = Nodes$XNode@7f59c7
>>>
>>> scala> val y = new YNode
>>> y: nodes.YNode = Nodes$YNode@247bd2
>>>
>>> scala> x.reg
>>> res0: NodeRegistry = NodeRegistry@b72911
>>>
>>> scala> y.reg
>>> res1: NodeRegistry = NodeRegistry@b72911
>>>
>>> scala>
>>>
>>> - Colin
>>>
>>>
>>
>> But that will mean I have to define all my XNode classes inside trait
>> Nodes,
>> doesn't it? In the Java example I could have done this insode the
>> NodeRegsitry class. But as I understand it, traits, just like Java
>> classes,
>> are not 'open' like packages (or a better example: C++ namespaces) are in
>> that you can add to them from multiple source files.
>>
>> My problem is that a number of core classes is inside the framework but
>> in
>> application code many classes will be derived (extended) from these
>> classes.
>> Therefore, I need an open construction.
>>
>> Since Node instances will only be created inside methods of already
>> existing
>> Node instances I would like some implicit instance passing, just like
>> with
>> nested classes in Java, but then extended accross multiple source files.
>>
>> The Java limitation that a top-level class can not extend a nested class
>> is
>> imho. a language choice. It would have been possible to allow this,
>> demanding that such top level classes could only be instantiated inside
>> the
>> scope of an instance of the surrounding class of the base. I was hoping
>> that
>> Scala would allow me to do this.
>>
>> Still looking for a solution.
>>
>> --
>> View this message in context:
>> http://www.nabble.com/Scala-and-%28non-%29nested-classes-question-tp2208...
>> Sent from the Scala - User mailing list archive at Nabble.com.
>>
>>
>
>

That is obvious. I should have said 'inner class' since that is what a non
static nested class is called.

Anyway, the implicit reference to the enclosing instance (which also enables
acces to members of the enclosing class instance) is the whole point. I was
hoping to use that as the common context.

Silvio

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 4 days ago.
Re: Scala and (non-)nested classes question
I'm not sure I understand what your requirements are, but perhaps you're looking for something like:

  class NodeRegistry
  class BaseNode(implicit val registry: NodeRegistry)

If an implicit val is in scope, then you can say "new BaseNode" or "extends BaseNode" with no parameters. If an implicit val isn't in scope, then you'll have to specify it as a parameter explicitly. A BaseNode's registry will be implicitly in scope for all its instances regardless of subclass.

--j

On Wed, Feb 18, 2009 at 1:06 PM, Silvio Bierman <sbierman@jambo-software.com> wrote:



Giovanni De Facci wrote:
>
>>> The Java limitation that a top-level class can not extend a nested class
>>> is
>>> imho. a language choice.
>
> // compilation unit SuperContainer
>
> public class SupContainer {
>
>       public static class Sup {
>
>       }
> }
>
> // compilation unit Sub
>
> public class Sub extends SupContainer.Sup {
>
> }
>
> In java top level classes can extend inner classes. Top level classes
> cant extend non static inner classes, since non static inner classes
> can access members of the class in which they are defined.
>
> best regards
>
> G
>
> On 2/18/09, Silvio Bierman <sbierman@jambo-software.com> wrote:
>>
>>
>>
>> Colin Bullock wrote:
>>>
>>> One potential solution:
>>>
>>> class NodeRegistry
>>> class BaseNode(val reg: NodeRegistry)
>>>
>>> trait NodeRegistryComponent {
>>>   def registry: NodeRegistry
>>> }
>>>
>>> trait Nodes {
>>>   self: NodeRegistryComponent =>
>>>
>>>   class XNode extends BaseNode(registry)
>>>   class YNode extends BaseNode(registry)
>>>   // ...
>>> }
>>>
>>> object nodes extends Nodes with NodeRegistryComponent {
>>>   override val registry = new NodeRegistry
>>> }
>>>
>>> scala> import nodes._
>>> import nodes._
>>>
>>> scala> val x = new XNode
>>> x: nodes.XNode = Nodes$XNode@7f59c7
>>>
>>> scala> val y = new YNode
>>> y: nodes.YNode = Nodes$YNode@247bd2
>>>
>>> scala> x.reg
>>> res0: NodeRegistry = NodeRegistry@b72911
>>>
>>> scala> y.reg
>>> res1: NodeRegistry = NodeRegistry@b72911
>>>
>>> scala>
>>>
>>> - Colin
>>>
>>>
>>
>> But that will mean I have to define all my XNode classes inside trait
>> Nodes,
>> doesn't it? In the Java example I could have done this insode the
>> NodeRegsitry class. But as I understand it, traits, just like Java
>> classes,
>> are not 'open' like packages (or a better example: C++ namespaces) are in
>> that you can add to them from multiple source files.
>>
>> My problem is that a number of core classes is inside the framework but
>> in
>> application code many classes will be derived (extended) from these
>> classes.
>> Therefore, I need an open construction.
>>
>> Since Node instances will only be created inside methods of already
>> existing
>> Node instances I would like some implicit instance passing, just like
>> with
>> nested classes in Java, but then extended accross multiple source files.
>>
>> The Java limitation that a top-level class can not extend a nested class
>> is
>> imho. a language choice. It would have been possible to allow this,
>> demanding that such top level classes could only be instantiated inside
>> the
>> scope of an instance of the surrounding class of the base. I was hoping
>> that
>> Scala would allow me to do this.
>>
>> Still looking for a solution.
>>
>> --
>> View this message in context:
>> http://www.nabble.com/Scala-and-%28non-%29nested-classes-question-tp22081498p22083079.html
>> Sent from the Scala - User mailing list archive at Nabble.com.
>>
>>
>
>

That is obvious. I should have said 'inner class' since that is what a non
static nested class is called.

Anyway, the implicit reference to the enclosing instance (which also enables
acces to members of the enclosing class instance) is the whole point. I was
hoping to use that as the common context.

Silvio

--
View this message in context: http://www.nabble.com/Scala-and-%28non-%29nested-classes-question-tp22081498p22088209.html
Sent from the Scala - User mailing list archive at Nabble.com.


Silvio Bierman
Joined: 2009-02-16,
User offline. Last seen 1 year 16 weeks ago.
Re: Scala and (non-)nested classes question

That sounds very promising. Might just solve my problem, I will look into
this in more detail.

Thanks a lot.

Silvio

Jorge Ortiz-3 wrote:
>
> I'm not sure I understand what your requirements are, but perhaps you're
> looking for something like:
>
> class NodeRegistry
> class BaseNode(implicit val registry: NodeRegistry)
>
> If an implicit val is in scope, then you can say "new BaseNode" or
> "extends
> BaseNode" with no parameters. If an implicit val isn't in scope, then
> you'll
> have to specify it as a parameter explicitly. A BaseNode's registry will
> be
> implicitly in scope for all its instances regardless of subclass.
>
> --j
>
>

Silvio Bierman
Joined: 2009-02-16,
User offline. Last seen 1 year 16 weeks ago.
Re: Scala and (non-)nested classes question

That sounds very promising. Might just solve my problem, I will look into
this in more detail.

Thanks a lot.

Silvio

Jorge Ortiz-3 wrote:
>
> I'm not sure I understand what your requirements are, but perhaps you're
> looking for something like:
>
> class NodeRegistry
> class BaseNode(implicit val registry: NodeRegistry)
>
> If an implicit val is in scope, then you can say "new BaseNode" or
> "extends
> BaseNode" with no parameters. If an implicit val isn't in scope, then
> you'll
> have to specify it as a parameter explicitly. A BaseNode's registry will
> be
> implicitly in scope for all its instances regardless of subclass.
>
> --j
>
>

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland