Skip to content
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

Nameless classes #2927

Open
jodinathan opened this issue Mar 17, 2023 · 4 comments
Open

Nameless classes #2927

jodinathan opened this issue Mar 17, 2023 · 4 comments
Labels
request Requests to resolve a particular developer problem

Comments

@jodinathan
Copy link

Do we have any feature planned that enables creating nameless classes or structures?

I thought Records would be like that but it has fields instead of properties so you can't have a getter or a setter there.

@jodinathan jodinathan added the request Requests to resolve a particular developer problem label Mar 17, 2023
@mateusfccp
Copy link
Contributor

Could you please provide what use-cases you expect to cover to these? I can't really see the value of adding nameless classes.

@ykmnkmi
Copy link

ykmnkmi commented Mar 17, 2023

Same as Java anonymous classes.

AngularDart TemplateAstVisitor:

var visitor = TemplateAstVisitor<void, Object>() {
  @override
  void visitText(TextAst astNode, [Object? context]) {
    print(astNode.value.isEmpty ? '<empty-text>' : astNode.value);
  }
};

textNode.visit(visitor);

In Flutter:

class MyHomepage extends StatefulWidget {
  const MyHomepage({super.key});

  @override
  State<MyHomepage> createState() => State<MyHomepage>() {
    int index = 0;

    @override
    Widget build(BuildContext context) {
      return BottomNavigationBar(
        currentIndex: index,
        onTap: (newIndex) {
          setState(() {
            index = newIndex;
          });
        },        
      );
    }
  };
}

@munificent
Copy link
Member

We don't currently have any plans to do anonymous classes. While I've used them in other languages, I rarely find much desire for them in Dart. In Java, they were most heavily used to implement single-method interfaces. Those are, of course, much better served in Dart (and Java today) by simply using closures and method tear-offs.

To create an anonymous implementation of an interface with multiple methods, it's pretty easy to write a proxy class that takes a couple of closures and forwards to them:

abstract class Command {
  void redo();
  void undo();
}

class ClosureCommand implements Command {
  final void Function() _redo;
  final void Function() _undo;

  ClosureCommand(this._redo, this._undo);

  @override
  void redo() => _redo();

  @override
  void undo() => _undo();
}

main() {
  var command = ClosureCommand(
      () => print('redo'),
      () => print('undo'));
}

@lrhn
Copy link
Member

lrhn commented Apr 25, 2024

Creating an anonumous class instance can be more convenient than having to create the class to hold the closures and call them.

I actually think it could be a good feature, that would allow more uses of classes in places where we have so far used closures. Passing three or four closures to a function may actually be better served by a parameter object created as an anonymous class instance. Imagine:

stream.listen(StreamEventSink() {
  int count = 0;
  void onData(T value) { if (++count <= max) print(value); }
  void onDone() { if (count < max) print("Not enough!"); }
});

It has better encapsulation than just passing in closures.

A bigger issue is that it allows declaring instance methods in an instance member body scope.

main() {
   final name = "Banana";
   const id = 42;
   var command = Command() {
      void redo() {
        log("$name:$id:redo");
      }
      void undo() {
        log("$name:$id:undo");
      }
   };
   // use command
}

If we allow this code, then we now have instances that close over local variables.

Java doesn't allow that in general, it only allows closing over final variables, which means they can just store the value in the object when it's created.
Maybe Dart can do something similar. Or we can allow closing over variables (closures can, so the functionality is there, may just have to store a setter and a getter function per mutable variables being closed over).

It's a design decision with some consequences, so this feature definitely isn't a design slam-dunk. The grammar and the meaning of declaring a class inside function body code is not clear and obvious.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request Requests to resolve a particular developer problem
Projects
None yet
Development

No branches or pull requests

5 participants