New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: support for nested classes. #3755

Open
DartBot opened this Issue Jun 19, 2012 · 20 comments

Comments

@DartBot
Copy link

DartBot commented Jun 19, 2012

This issue was originally filed by zhygrr...@gmail.com


It would be nice if we can introduce classes local to a given enclosing class.

class Outer {
  void doSomething() {
    var inner = new Inner();
  }
  class _Inner {
       
  }
}

This allows define class that is invisible outside of the Outer class scope.

I understand that this feature requires more investigation. As for me it has a limited power if a class is not the first class object (or a class could be a class member like fields or methods).

@sethladd

This comment has been minimized.

Copy link
Member

sethladd commented Jun 22, 2012

Removed Type-Defect label.
Added Type-Enhancement, Area-Language, Triaged labels.

@gbracha

This comment has been minimized.

Copy link
Contributor

gbracha commented Jun 26, 2012

The idea of nested classes is very familiar to us (see. e.g., Beta, Newspeak). To avoid any misunderstandings, I should make it clear that we would NOT do this the way it was done in the Java programming language. Whether this will happen in Dart is an open question.


Set owner to @gbracha.
Added this to the Later milestone.
Added Accepted label.

@DartBot

This comment has been minimized.

Copy link
Author

DartBot commented Mar 26, 2014

This comment was originally written by astimo...@gmail.com


I would be very happy if inner classes were only a means of taking advantage of lexical scoping for the organization of classes by name.

class Foo
{
  Bar bar;
  Baz baz;

  Foo()
  {
    bar = new Bar();
    baz = new Baz();
  }

  class Bar
  {
  }

  class _Baz
  {
  }
}

new Foo.Bar(); // acceptable
new Foo._Baz(); // unacceptable

By "only a means of taking advantage of lexical scope" I mean to exclude the java behaviour of creating a runtime reference to the outer class unless the inner class is declared static. For that case the program can explicitly provide the outer class to the inner class.

Thus the following will not work:

class Foo
{
  Bar bar;

  Foo()
  {
    bar = new Bar();
    bar.speak();
  }

  void hello()
  {
    print("hello");
  }

  class Bar()
  {
    void speak()
    {
      hello();
    }
  }
}

But this will work:

class Foo
{
  Bar bar;

  Foo()
  {
    bar = new Bar(this);
    bar.speak();
  }
  
  void hello()
  {
    print("hello");
  }

  class Bar
  {
    final Foo foo;

    Bar(Foo foo)
    {
      this.foo = foo;
    }

    void speak()
    {
      foo.hello();
    }
  }
}

@kasperl

This comment has been minimized.

Copy link
Contributor

kasperl commented Jul 10, 2014

Removed this from the Later milestone.
Added Oldschool-Milestone-Later label.

@kasperl

This comment has been minimized.

Copy link
Contributor

kasperl commented Aug 4, 2014

Removed Oldschool-Milestone-Later label.

@DartBot

This comment has been minimized.

Copy link
Author

DartBot commented Sep 30, 2014

This comment was originally written by PortalProgra...@gmail.com


Any updates on this issue?

@gbracha

This comment has been minimized.

Copy link
Contributor

gbracha commented Oct 6, 2014

Not really.

@MikeMitterer

This comment has been minimized.

Copy link

MikeMitterer commented Mar 7, 2017

It quite often the case that an enum has a very strong relation to a class - because of this missing feature I can't write "inner-enums" - annoying.

@zoechi

This comment has been minimized.

Copy link
Contributor

zoechi commented Mar 8, 2017

You can make the enum library-private. Not the same of course, but quite close.

@MikeMitterer

This comment has been minimized.

Copy link

MikeMitterer commented Mar 9, 2017

Thanks - I know. But this:

class MyCoolClass {
    enum Props { HOT, NEW, COOL }
    ...
}
...
switch(props) {
    case MyCoolClass.Props.HOT:
    break;
    ...
}

is what I want.

I know - in Java its a bit problematic if the inner class is not static - C++ does it right. Dart should have a similar thing.

@zoechi

This comment has been minimized.

Copy link
Contributor

zoechi commented Mar 9, 2017

I got it that you want that. The question is if it's worth to complicate the language for that.
What's the advantage of having it inside the class instead of outside, that makes it worth to make the language more complex?
I'm not arguing against it. Just curious what you think would be the big advantage.

@xster

This comment has been minimized.

Copy link

xster commented Mar 9, 2017

I think it's just for the communications/maintainability scalability of a systems engineering language.
Referring to say network.get(..., cache: Network.CachingStrategy.A) (which is a public API) is cleaner than having a NetworkCachingStrategy global class/enum lying around all the time.

@MichaelRFairhurst

This comment has been minimized.

Copy link
Contributor

MichaelRFairhurst commented Mar 9, 2017

I would agree. One thing I would say as well, is that I think very rarely should dart files define multiple classes.

Usually when I do see it I don't disagree with the structuring of the code, but I do find it hard to use the resulting api.

import 'something.dart';

...
  var something = new Something();
  something.use(new UsedBySomething());
  new FinalizesSomethings.finalize(something);

There's no easy autocomplete for "what does the something package expose again?" Its also hard when reusing this code elsewhere, to figure out which import brings in which classes.

You could do prefixed imports, but now you've either got the tedious something.Something or you've got the cryptic smt.Something. Oh and you can no longer use smt or something as variables when you do this.

I think it would be a nice improvement if we only ever defined one class in a dart file, and relied on inner classes where they are so related that they deserve to be in the same file.

  var something = new Something();
  something.use(new Something.UsesThis());
  new Something.Finalizer(something)

You may also not be surprised to hear that I think this is less of an issue when the classes are named CommonFoo rather than FooCommon since that's basically what my new code is, just with an extra dot. But its pretty common that these things don't match up perfectly. And even then, you never know when "SomethingFinalizer" is in "something.dart" or "something_finalizer.dart".

Obviously there's a conflict here with the syntax, as Finalizer could be the name of a constructor on Something rather than a class on Something. Probably would be a ton of work to solve.

Overall my opinion is that it would be a small but appreciable win for dart.

@gdejohn

This comment has been minimized.

Copy link

gdejohn commented Mar 7, 2018

I should make it clear that we would NOT do this the way it was done in the Java programming language.

@gbracha In what way would you do it differently in Dart?

@eernstg

This comment has been minimized.

Copy link
Member

eernstg commented Mar 7, 2018

(PS: Gilad is not in the Dart team now, he went on to pursue new adventures elsewhere.)

That said, I think this is the right place to gather arguments for or against adding class nesting (static or otherwise) to Dart, but also that there is relatively modest support for the idea at this point.

@gdejohn

This comment has been minimized.

Copy link

gdejohn commented Mar 12, 2018

@eernstg Do you have any idea what Gilad meant about doing it differently than Java?

@MikeMitterer

This comment has been minimized.

Copy link

MikeMitterer commented Mar 14, 2018

@eernstg Maybe like Kotlin - where an inner class is always static (Doesn't have a reference to it's outer class) except it is marked with the "inner" keyword
https://kotlinlang.org/docs/reference/nested-classes.html

@eernstg

This comment has been minimized.

Copy link
Member

eernstg commented Mar 14, 2018

Gilad's Newspeak includes nested classes, and they are related to the general nesting in BETA and gbeta (of patterns, which is a general concept that includes classes and a lot of other things in one language mechanism), and those languages all make nested classes members in a way that resembles methods (in particular, a nested class is subject to late binding). That's a rather powerful concept, aka virtual classes or virtual patterns, and — who knows — that might have been on his mind when he said ''we would NOT do this [like in Java]".

On the other hand, static inner classes are even less powerful than Java inner classes, they provide nothing else than scoping (that is, certain things will have shorter names in some contexts). So I doubt it was that.

In any case, virtual classes in Dart would be such a huge generalization (of many things, including the type system), so we won't get that in any reasonable amount of time. ;-)

@gusterwoei-veltra

This comment has been minimized.

Copy link

gusterwoei-veltra commented Apr 24, 2018

Yea I was trying to build a JSON to object mapping library but got stuck in this issue.

@phlebotinum

This comment has been minimized.

Copy link

phlebotinum commented Oct 18, 2018

I want Enums as sub-types of classes for more code clarity.

@lrhn lrhn added core-m and removed p2-medium labels Dec 6, 2018

@lrhn lrhn added this to Non-Breaking and Complex in Language Enhancement Categories Dec 14, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment