如何确保代码在继承时以特定顺序执行

How to ensure code is executed in a specific order on inheritance

我有这个超级 class 扩展 TableView,我想制作的每个 table 都应该继承自。

这行代码需要为每个继承自 superclass 并需要 ContextMenu:

的 class 执行
// Sets the context menu for each specific row. This way no
// context menu will appear if we click on a row that is
// empty.
setRowFactory(r -> {
    TableRow<ObservableList<String>> row = new TableRow<ObservableList<String>>() {
        public void updateItem(ObservableList<String> item, boolean empty) {
            super.updateItem(item, empty);
            if (isEmpty()) {
                setContextMenu(null);
            } else {
                setContextMenu(contextMenu);
            }
        }
    };
});

问题是 ContextMenu 需要在这段代码执行之前实例化,因此我不能放入超级 class.

的构造函数

如果 table 需要 ContextMenu(不总是案例):

  1. MenuItem 个实例实例化 ContextMenu(我想 MenuItem 个实例理论上可以在以后实例化和添加)。
  2. 使用在步骤 1 中实例化的上下文菜单调用上面的 "setRowFactory" 代码。

我已经多次尝试解决这个问题,但仍然没有找到令人满意的解决方案。也许我遗漏了一些明显的东西。

编辑: 如果您能以某种方式禁止用户使用 TableView 的原始 setContextMenu 方法以确保 `ContextMenu 是完美的以正确的方式添加。但我想这是不可能的。

看起来您只是想禁止在 table 中的空行上显示上下文菜单。更简单的方法是

public class MyTableView<T> extends TableView<T> {

    public MyTableView() {
        setRowFactory(tv -> {
            TableRow<T> row = new TableRow<>();
            row.setOnContextMenuRequested(e -> {
                if (row.isEmpty()) {
                    e.consume();
                }
            }
            return row ;
        });
    }

    // ...
}

回答您提出的问题(确保您只(且始终)在致电 setContextMenu 后致电 setRowFactory):

你可以做

public class MyTableView<T> extends TableView<T> {

    private final ContextMenu contextMenu ;

    public MyTableView(ContextMenu contextMenu) {
        this.contextMenu = contextMenu ;

        setRowFactory(r -> {
            TableRow<ObservableList<String>> row = new TableRow<ObservableList<String>>() {
                public void updateItem(ObservableList<String> item, boolean empty) {
                    super.updateItem(item, empty);
                    if (isEmpty()) {
                        setContextMenu(null);
                    } else {
                        setContextMenu(contextMenu);
                    }
                }
            };
        });

    }

    // ...
}

public class MyTableView<T> extends TableView<T> {

    private ContextMenu rowContextMenu ;

    public ContextMenu getRowContextMenu() {
        return rowContextMenu ;
    }

    public void setRowContextMenu(ContextMenu contextMenu) {
        this.rowContextMenu = contextMenu ;

        setRowFactory(r -> new TableRow<ObservableList<String>>() {
            public void updateItem(ObservableList<String> item, boolean empty) {
                super.updateItem(item, empty);
                if (isEmpty()) {
                    setContextMenu(null);
                } else {
                    setContextMenu(rowContextMenu);
                }
            }
        });
    }

    // ...
}

甚至

public class MyTableView<T> extends TableView<T> {

    public MyTableView() {
        contextMenuProperty().addListener((obs, oldContextMenu, newContextMenu) -> {
            if (newContextMenu == null) {
                setRowFactory(r -> new TableRow<>());
            } else 
                setRowFactory(r -> new TableRow<ObservableList<String>>() {
                    public void updateItem(ObservableList<String> item, boolean empty) {
                        super.updateItem(item, empty);
                        if (isEmpty()) {
                            setContextMenu(null);
                        } else {
                            setContextMenu(newContextMenu);
                        }
                    }
                });
            }
        });
    }

    // ...
}