微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在闭包中捕获 int 值?

如何解决如何在闭包中捕获 int 值?

我有一个应用程序,其中包含任意数量的元素,这些元素都调用一个需要接受参数的函数,该函数在创建时定义。这是一个简化的示例,但在这里我希望制作 3 个打印 0、1、2 的按钮,但只制作 3 个打印 3 的按钮。

    var application_window = new Gtk.applicationwindow (this);
    var grid = new Gtk.Grid ();

    for (int i = 0; i < 3; i++) {
        var button = new Gtk.Button() {expand=true};
        button.clicked.connect (() => {
                print(i.to_string());
        });

        grid.add(button);
    }

    application_window.add(grid);
    application_window.show_all ();

如何将我的应用更改为打印 123?

解决方法

这是我的基本代码:

public class MyApplication : Gtk.Application {
    public MyApplication () {
        Object(application_id: "testing.my.application",flags : ApplicationFlags.FLAGS_NONE);
    }

    protected override void activate () {
        var application_window = new Gtk.ApplicationWindow (this);
        var grid = new Gtk.Grid ();

        for (int i = 0; i < 3; i++) {
            var button = new Gtk.Button() {expand=true};
            button.clicked.connect (() => {
                print(i.to_string());
            });

            grid.add(button);
        }

        application_window.add(grid);
        application_window.show_all ();
    }

    public static int main (string[] args) {
        MyApplication app = new MyApplication ();
        return app.run (args);
    }
}

如果你这样执行它,你会得到 333 作为标准输出。

问题出在捕获代码上:

for (int i = 0; i < 3; i++) {
    var button = new Gtk.Button() {expand=true};
    button.clicked.connect (() => {
        print(i.to_string());
    });

闭包正在按位置捕获变量 i。这意味着当您在创建闭包后更改 i 变量时,该更改也将在闭包中可见。

其他编程语言(例如 C++)有明确的捕获列表来避免这个问题。

一个快速而肮脏的解决方案是在循环范围内使用局部变量:

for (int i = 0; i < 3; i++) {
    var captured_i = i;
    var button = new Gtk.Button() {expand=true};
    button.clicked.connect (() => {
        print(captured_i.to_string());
    });

这会按预期打印:012

更好的解决方案是使用将闭包作为委托返回的函数。我刚刚尝试过,但由于某种原因它不起作用:

public class MyApplication : Gtk.Application {
    public MyApplication () {
        Object(application_id: "testing.my.application",flags : ApplicationFlags.FLAGS_NONE);
    }

    delegate void ButtonClick();

    private ButtonClick make_print_event (int i) {
        return () => print (i.to_string());
    }    

    protected override void activate () {
        var application_window = new Gtk.ApplicationWindow (this);
        var grid = new Gtk.Grid ();

        for (int i = 0; i < 3; i++) {
            var button = new Gtk.Button() { expand=true };
            var print_event = make_print_event (i);
            button.clicked.connect (print_event);
            grid.add(button);
        }

        application_window.add (grid);
        application_window.show_all ();
    }

    public static int main (string[] args) {
        MyApplication app = new MyApplication ();
        return app.run (args);
    }
}

编译器 (valac-0.52) 警告:

three_buttons.vala:20.37-20.47: warning: copying delegates is not supported
three_buttons.vala:20.37-20.47: warning: Connecting delegates to signals is experimental
            button.clicked.connect (print_event);
                                    ^^^^^^^^^^^

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?