123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:pls="http://www.w3.org/2005/01/pronunciation-lexicon" xmlns:ssml="http://www.w3.org/2001/10/synthesis" xmlns:svg="http://www.w3.org/2000/svg">
- <head>
- <title>Allocating objects</title>
- <link rel="stylesheet" type="text/css" href="docbook-epub.css"/>
- <link rel="stylesheet" type="text/css" href="kawa.css"/>
- <script src="kawa-ebook.js" type="text/javascript"/>
- <meta name="generator" content="DocBook XSL-NS Stylesheets V1.79.1"/>
- <link rel="prev" href="Method-operations.xhtml" title="Calling Java methods from Scheme"/>
- <link rel="next" href="Field-operations.xhtml" title="Accessing object fields"/>
- </head>
- <body>
- <header/>
- <section class="sect1" title="Allocating objects" epub:type="subchapter" id="Allocating-objects">
- <div class="titlepage">
- <div>
- <div>
- <h2 class="title" style="clear: both">Allocating objects</h2>
- </div>
- </div>
- </div>
- <p>The recommended way to create an instance of a type <em class="replaceable"><code>T</code></em>
- is to “call” <em class="replaceable"><code>T</code></em> as if it were a function, with the
- arguments used to initialize the object.
- If <code class="literal">T</code> is a class and <code class="literal">T</code> has a matching constructor,
- then the arguments will used for constructor arguments:
- </p>
- <pre class="screen">(java.util.StringTokenizer "this/is/a/test" "/")
- </pre>
- <p>(You can think of the type <em class="replaceable"><code>T</code></em> as being
- coerced to an instance-constructor function.)
- </p>
- <p>If <code class="literal">T</code> is a container or collection type,
- then typically the arguments will be used to specify
- the child or component values.
- Many standard Scheme procedures fit this convention.
- For example in Kawa <code class="literal">list</code> and <code class="literal">vector</code> evaluate to
- types, rather than procedures as in standard Scheme,
- but because types can be used as constructor functions it just works:
- </p>
- <pre class="screen">(list 'a (+ 3 4) 'c) ⇒ (a 7 c)
- (vector 'a 'b 'c) ⇒ #(a b c)
- </pre>
- <p>Any class <code class="literal">T</code> that has a default constructor
- and an <code class="literal">add</code> method can be initialized this way.
- Examples are <code class="literal">java.util</code> collection classes,
- and <code class="literal">jawa.awt</code> and <code class="literal">javax.swing</code> containers.
- </p>
- <pre class="screen">(java.util.ArrayList 11 22 33) ⇒ [11, 22, 333]
- </pre>
- <p>The above expression is equivalent to:
- </p>
- <pre class="screen">(let ((tmp (java.util.ArrayList)))
- (tmp:add 11)
- (tmp:add 22)
- (tmp:add 33)
- tmp)
- </pre>
- <p>Allocating Java arrays (see <a class="link" href="Array-operations.xhtml#Creating-new-Java-arrays">Creating-new-Java-arrays</a>) uses a
- similar pattern:
- </p>
- <pre class="screen">(int[] 2 3 5 7 11)
- </pre>
- <p>Sometimes you want to set some named property to an initial value.
- You can do that using a keyword argument. For example:
- </p>
- <pre class="screen">(javax.swing.JButton text: "Do it!" tool-tip-text: "do it")
- </pre>
- <p>This is equivalent to using <em class="firstterm">setter methods</em>:
- </p>
- <pre class="screen">(let ((tmp (javax.swing.JButton)))
- (tmp:setText "Do it!")
- (tmp:setToolTipText "do it")
- tmp)
- </pre>
- <p>A keyword argument <code class="literal"><em class="replaceable"><code>key-name</code></em></code><code class="literal"><span class="bold"><strong>:</strong></span></code> can
- can translated to either a <code class="literal"><code class="literal"><span class="bold"><strong>set</strong></span></code><em class="replaceable"><code>KeyName</code></em><code class="literal"><span class="bold"><strong>:</strong></span></code></code>
- or a <code class="literal"><code class="literal"><span class="bold"><strong>add</strong></span></code><em class="replaceable"><code>KeyName</code></em><code class="literal"><span class="bold"><strong>:</strong></span></code></code> method.
- The latter makes it convenient to add listeners:
- </p>
- <pre class="screen">(javax.swing.JButton
- text: "Do it!"
- action-listener:
- (object (java.awt.event.ActionListener)
- ((actionPerformed e) (do-the-action))))
- </pre>
- <p>This is equivalent to:
- </p>
- <pre class="screen">(let ((tmp (javax.swing.JButton)))
- (tmp:setText "Do it!")
- (tmp:addActionListener
- (object (java.awt.event.ActionListener)
- ((actionPerformed e) (do-the-action))))
- tmp)
- </pre>
- <p>Making use of so-called “SAM-conversion” (see <a class="link" href="Anonymous-classes.xhtml#SAM-conversion">SAM-conversion</a>)
- makes it even more convenient:
- </p>
- <pre class="screen">(javax.swing.JButton
- text: "Do it!"
- action-listener:
- (lambda (e) (do-the-action)))
- </pre>
- <p>The general case allows for a mix of
- constructor arguments, property keywords, and child values:
- </p>
- <div class="literallayout">
- <p><em class="replaceable"><code>class-type</code></em> <a class="link" href="Allocating-objects.xhtml#meta-constructor-value"><em class="replaceable"><code>constructor-value</code></em></a>... <a class="link" href="Allocating-objects.xhtml#meta-property-initializer"><em class="replaceable"><code>property-initializer</code></em></a>... <a class="link" href="Allocating-objects.xhtml#meta-child-value"><em class="replaceable"><code>child-value</code></em></a>...<br/>
- <a id="idm139667870938720" class="indexterm"/><span id="meta-constructor-value"/><em class="replaceable"><code>constructor-value</code></em> <code class="literal">::=</code> <a class="link" href="Primitive-expression-syntax.xhtml#meta-expression"><em class="replaceable"><code>expression</code></em></a><br/>
- <a id="idm139667870935920" class="indexterm"/><span id="meta-property-initializer"/><em class="replaceable"><code>property-initializer</code></em> <code class="literal">::=</code> <a class="link" href="Keywords.xhtml#meta-keyword"><em class="replaceable"><code>keyword</code></em></a> <a class="link" href="Primitive-expression-syntax.xhtml#meta-expression"><em class="replaceable"><code>expression</code></em></a><br/>
- <a id="idm139667870932288" class="indexterm"/><span id="meta-child-value"/><em class="replaceable"><code>child-value</code></em> <code class="literal">::=</code> <a class="link" href="Primitive-expression-syntax.xhtml#meta-expression"><em class="replaceable"><code>expression</code></em></a><br/>
- </p>
- </div>
- <p>First an object is constructed with the <em class="replaceable"><code>constructor-value</code></em> arguments
- (if any) passed to the object constructor;
- then named properties (if any) are used to initialize named properties;
- and then remaining arguments are used to add child values.
- </p>
- <p>There is an ambiguity if there is no <em class="replaceable"><code>property-initializer</code></em> -
- we can’t distinguish between a <em class="replaceable"><code>constructor-value</code></em>
- and a <em class="replaceable"><code>child-value</code></em>.
- In that case, if there is a matching constructor method, then all of the
- arguments are constructor arguments;
- otherwise, there must a default constructor, and all
- of the arguments are <em class="replaceable"><code>child-value</code></em> arguments.
- </p>
- <p>There is a trick you can you if you need both
- <em class="replaceable"><code>constructor-value</code></em> and <em class="replaceable"><code>child-value</code></em> arguments:
- separate them with an “empty keyword” <code class="literal">||:</code>.
- This matches a method named <code class="literal">add</code>, which means that
- the next argument effectively a <em class="replaceable"><code>child-value</code></em> - as do
- all the remaining arguments. Example:
- </p>
- <pre class="screen">(let ((vec #(1 2 3)))
- (java.util.ArrayList vec ||: 4 5 6))
- ⇒ [1, 2, 3, 4, 5, 6]
- </pre>
- <p>The compiler rewrites these allocations expression
- to generated efficient bytecode, assuming that the “function”
- being applied is a type known by the compiler.
- Most of the above expressions also work if the type is applied
- at run-time, in which case Kawa has to use slower reflection:
- </p>
- <pre class="screen">(define iarr int[])
- (apply iarr (list 3 4 5)) ⇒ [3 4 5]
- </pre>
- <p>However <code class="literal">add<em class="replaceable"><code>Xxx</code></em></code> methods and SAM-conversion
- are currently only recognized in the case of a class known at compile-time,
- not at run-time.
- </p>
- <p>Here is a working Swing demo illustrating many of these techniques:
- </p>
- <pre class="screen">(import (class javax.swing
- JButton Box JFrame))
- (define-simple-class HBox (Box)
- ((*init*) (invoke-special Box (this) '*init* 0)))
- (define value 0)
- (define txt
- (javax.swing.JLabel
- text: "0"))
- (define (set-value i)
- (set! value i)
- (set! txt:text (number->string i)))
- (define fr
- (JFrame
- title: "Hello!"
- (Box 1#|VERTICAL|# ||:
- (javax.swing.Box:createGlue)
- txt
- (javax.swing.Box:createGlue)
- (HBox
- (JButton ;; uses 1-argument constructor
- "Decrement" ;; constructor argument
- tool-tip-text: "decrement"
- action-listener: (lambda (e) (set-value (- value 1))))
- (javax.swing.Box:createGlue)
- (JButton ;; uses 0-argument constructor
- text: "Increment"
- tool-tip-text: "increment"
- action-listener: (lambda (e) (set-value (+ value 1))))))))
- (fr:setSize 200 100)
- (set! fr:visible #t)
- </pre>
- <p>If you prefer, you can use the older <code class="literal">make</code> special function:
- </p>
- <p class="synopsis" kind="Procedure"><span class="kind">Procedure</span><span class="ignore">: </span><a id="idm139667870916928" class="indexterm"/> <code class="function">make</code> <em class="replaceable"><code>type</code></em> <em class="replaceable"><code>args</code></em> <em class="replaceable"><code>...</code></em></p>
- <div class="blockquote">
- <blockquote class="blockquote">
- <p>Constructs a new object instance of the specified <em class="replaceable"><code>type</code></em>,
- which must be either a <code class="literal">java.lang.Class</code> or a
- <code class="literal"><gnu.bytecode.ClassType></code>.
- Equivalent to:
- </p>
- <pre class="screen"><em class="replaceable"><code>type</code></em> <em class="replaceable"><code>args</code></em> ...
- </pre>
- </blockquote>
- </div>
- <p>Another (semi-deprecated) function is to use the colon notation
- with the <code class="literal">new</code> pseudo-function.
- The following three are all equivalent:
- </p>
- <pre class="screen">(java.awt.Point:new x: 4 y: 3)
- (make java.awt.Point: x: 4 y: 3)
- (java.awt.Point x: 4 y: 3)
- </pre>
- </section>
- <footer>
- <div class="navfooter">
- <p>
- Up: <a accesskey="u" href="Objects-Classes-and-Modules.xhtml">Object, Classes and Modules</a></p>
- <p>
- Previous: <a accesskey="p" href="Method-operations.xhtml">Calling Java methods from Scheme</a></p>
- <p>
- Next: <a accesskey="n" href="Field-operations.xhtml">Accessing object fields</a></p>
- </div>
- </footer>
- </body>
- </html>
|