Note that there are some explanatory texts on larger screens.

plurals
  1. POClojure defrecord and private fields
    text
    copied!<p>I frequently implement my Java swing GUIs using Martin Fowler's <a href="http://martinfowler.com/eaaDev/PresentationModel.html" rel="nofollow">Presentation Model</a> pattern.</p> <p>Here is an example:</p> <pre><code>import java.awt.BorderLayout; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListModel; interface MainView { void configurationButtonAddActionListener(ActionListener actionListener); void directoryLabelSetText(String text); ListModel fileListGetModel(); void setVisible(final boolean visible); } class MainFrame extends JFrame implements MainView { private final JButton configurationButton = new JButton("Configuration..."); private final JLabel directoryLabel = new JLabel(); private final JList fileList = new JList(); public MainFrame(final String title) { super(title); final JPanel mainPanel = new JPanel(new BorderLayout()); add(mainPanel); mainPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12)); mainPanel.add(directoryLabel, BorderLayout.NORTH); mainPanel.add(new JScrollPane(fileList)); mainPanel.add(configurationButton, BorderLayout.SOUTH); setSize(800, 600); setLocationRelativeTo(null); } @Override public void configurationButtonAddActionListener(final ActionListener actionListener) { configurationButton.addActionListener(actionListener); } @Override public void directoryLabelSetText(final String text) { directoryLabel.setText(text); } @Override public ListModel fileListGetModel() { return fileList.getModel(); } } </code></pre> <p>The interface can then be passed to a presenter class that is responsible for handling all actions on the view. A mock version can be passed into the presenter for testing and the view is so simple that, in theory, it does not need to be unit tested.</p> <p>I am trying to do something similar in Clojure using <code>defrecord</code>:</p> <pre><code>(ns mainframe (:gen-class) (:import [java.awt BorderLayout] [javax.swing JButton JFrame JLabel JList JPanel JScrollPane])) (if *compile-files* (set! *warn-on-reflection* true)) (defprotocol MainView (directory-label-set-text [this text]) (set-visible [this visible])) (defrecord mainframe [^JFrame frame directory-label file-list configuration-button] MainView (directory-label-set-text [this text] (.setText directory-label text)) (set-visible [this visible] (.setVisible frame visible))) (defn create-main-frame [title] (let [directory-label (JLabel.) file-list (JList.) configuration-button (JButton. "Configuration...") main-panel (doto (JPanel. (BorderLayout.)) (.add directory-label BorderLayout/NORTH) (.add (JScrollPane. file-list)) (.add configuration-button BorderLayout/SOUTH)) frame (doto (JFrame.) (.setTitle title) (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) (.add main-panel) (.setSize 800 600) (.setLocationRelativeTo nil))] (mainframe. frame directory-label file-list configuration-button))) </code></pre> <p>The only way I can up with to do the interface and "class" are using <code>defprotocol</code> and <code>defrecord</code>. Is there a better way? Is there any way to make the "fields" in the <code>defrecord</code> that contain the components (JButton, JLabel, JList) private? I dislike exposing the implementation details.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload