SCDoc: Use proper static string constants instead of comparing string literals.
[supercollider.git] / Help / Language / Polymorphism.html
blob1eb8434c971944708de94ba7d91afceff0de00e1
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5 <meta http-equiv="Content-Style-Type" content="text/css">
6 <title></title>
7 <meta name="Generator" content="Cocoa HTML Writer">
8 <meta name="CocoaVersion" content="949.43">
9 <style type="text/css">
10 p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica}
11 p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
12 p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
13 p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; min-height: 15.0px}
14 p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #000000}
15 p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 7.0px Monaco; min-height: 10.0px}
16 p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #bf0000}
17 p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #007300}
18 p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #0000bf}
19 p.p10 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #000000; min-height: 12.0px}
20 p.p11 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}
21 p.p12 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Helvetica; color: #000000; min-height: 11.0px}
22 p.p13 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #606060}
23 span.s1 {color: #0000bf}
24 span.s2 {color: #000000}
25 span.s3 {color: #007300}
26 span.s4 {color: #bf0000}
27 span.s5 {color: #606060}
28 span.Apple-tab-span {white-space:pre}
29 </style>
30 </head>
31 <body>
32 <p class="p1"><b>Polymorphism</b></p>
33 <p class="p2"><br></p>
34 <p class="p3">Polymorphism is the ability of different classes to respond to a message in different ways. A message generally has some underlying meaning and it is the responsibility of each class to respond in a way appropriate to that meaning.</p>
35 <p class="p2"><br></p>
36 <p class="p3">For example, the '<b>value</b>' message means "give me the effective value of this object".</p>
37 <p class="p2"><br></p>
38 <p class="p3">The value method is implemented by these classes (among others):</p>
39 <p class="p4"><br></p>
40 <p class="p5"><span class="s1">Function</span> : <span class="Apple-converted-space">  </span><span class="s1">this</span>.value(args)</p>
41 <p class="p5"><span class="s1">Object</span> : <span class="Apple-converted-space">  </span><span class="s1">this</span>.value()</p>
42 <p class="p5"><span class="s1">Ref</span> : <span class="Apple-converted-space">  </span><span class="s1">this</span>.value</p>
43 <p class="p4"><br></p>
44 <p class="p3">Let's look at how these classes implement the value message.</p>
45 <p class="p2"><br></p>
46 <p class="p3">Here's the value method in class <b>Object</b>:</p>
47 <p class="p2"><br></p>
48 <p class="p5"><span class="Apple-tab-span"> </span>value { ^<span class="s1">this</span> }</p>
49 <p class="p6"><br></p>
50 <p class="p3">It simply returns itself. Since all classes inherit from class Object this means that unless a class overrides 'value', the object will respond to 'value' by returning itself.</p>
51 <p class="p2"><br></p>
52 <p class="p7"><span class="s2">5.postln;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// posts itself</p>
53 <p class="p7"><span class="s2">5.value.postln;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// value returns itself</p>
54 <p class="p8">'a symbol'<span class="s2">.postln;</span></p>
55 <p class="p5"><span class="s3">'a symbol'</span>.value.postln;</p>
56 <p class="p5">[1,2,3].value.postln;</p>
57 <p class="p7">//etc...</p>
58 <p class="p2"><br></p>
59 <p class="p3">In class <b>Function</b> the value method is a primitive.</p>
60 <p class="p2"><br></p>
61 <p class="p5"><span class="Apple-tab-span"> </span>value { <span class="s1">arg</span> ... args;<span class="Apple-converted-space"> </span></p>
62 <p class="p9"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>_FunctionValue<span class="s2"><span class="Apple-converted-space"> </span></span></p>
63 <p class="p7"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// evaluate a function with args</p>
64 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>^<span class="s1">this</span>.primitiveFailed<span class="Apple-converted-space"> </span></p>
65 <p class="p5"><span class="Apple-tab-span"> </span>}</p>
66 <p class="p2"><br></p>
67 <p class="p2"><br></p>
68 <p class="p3">_FunctionValue is a C code primitive, so it is not possible to know just by looking at it what it does. However what it does is to evaluate the function and return the result.</p>
69 <p class="p2"><br></p>
70 <p class="p7"><span class="s2">{ 5.squared }.postln;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// posts Instance of Function</p>
71 <p class="p5">{ 5.squared }.value.postln;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s4">// posts 25</span></p>
72 <p class="p2"><br></p>
73 <p class="p3">The <b>Ref</b> class provides a way to create an indirect reference to an object. It can be used to pass a value by reference. Ref objects have a single instance variable called '<b>value</b>'. The '<b>value</b>' method returns the value of the instance variable '<b>value</b>'. Here is the class definition for <b>Ref</b>.</p>
74 <p class="p2"><br></p>
75 <p class="p9">Ref<span class="s2"> : </span>AbstractFunction<span class="s2"><span class="Apple-converted-space"> </span></span></p>
76 <p class="p5">{</p>
77 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">var</span> &lt;&gt;value;</p>
78 <p class="p5"><span class="Apple-tab-span"> </span>*new { <span class="s1">arg</span> thing; ^<span class="s1">super</span>.new.value_(thing) }</p>
79 <p class="p5"><span class="Apple-tab-span"> </span>set { <span class="s1">arg</span> thing; value = thing }</p>
80 <p class="p5"><span class="Apple-tab-span"> </span>get { ^value }</p>
81 <p class="p5"><span class="Apple-tab-span"> </span>dereference { ^value }</p>
82 <p class="p5"><span class="Apple-tab-span"> </span>asRef { ^<span class="s1">this</span> }</p>
83 <p class="p10"><br></p>
84 <p class="p7"><span class="s2"><span class="Apple-tab-span"> </span></span>//behave like a stream</p>
85 <p class="p5"><span class="Apple-tab-span"> </span>next { ^value }</p>
86 <p class="p5"><span class="Apple-tab-span"> </span>embedInStream { <span class="s1">arg</span> inval;</p>
87 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>^<span class="s1">this</span>.value.embedInStream(inval)</p>
88 <p class="p5"><span class="Apple-tab-span"> </span>}</p>
89 <p class="p10"><br></p>
90 <p class="p5"><span class="Apple-tab-span"> </span>printOn { <span class="s1">arg</span> stream;</p>
91 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>stream &lt;&lt; <span class="s5">"`("</span> &lt;&lt; value &lt;&lt; <span class="s5">")"</span>;</p>
92 <p class="p5"><span class="Apple-tab-span"> </span>}</p>
93 <p class="p5"><span class="Apple-tab-span"> </span>storeOn { <span class="s1">arg</span> stream;</p>
94 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>stream &lt;&lt; <span class="s5">"`("</span> &lt;&lt;&lt; value &lt;&lt; <span class="s5">")"</span>;</p>
95 <p class="p5"><span class="Apple-tab-span"> </span>}</p>
96 <p class="p5">}</p>
97 <p class="p11"><br></p>
98 <p class="p3">Here is how it responds :</p>
99 <p class="p11"><br></p>
100 <p class="p5"><span class="s1">Ref</span>.new(123).postln;</p>
101 <p class="p5"><span class="s1">Ref</span>.new(123).value.postln;</p>
102 <p class="p2"><br></p>
103 <p class="p3">Ref also implements a message called '<b>dereference</b>' which is another good example of polymorphism. As implemented in Ref, dereference just returns the value instance variable which is no different than what the value method does. So what is the need for it? That is explained by how other classes respond to dereference. The dereference message means "remove any Ref that contains you". In class Object dereference returns the object itself, again just like the value message. The difference is that no other classes override this method. So that dereference of a Function is still the Function.</p>
104 <p class="p2"><br></p>
105 <p class="p5"><span class="s1">Object</span> : <span class="Apple-converted-space">  </span><span class="s1">this</span>.dereference()</p>
106 <p class="p5"><span class="s1">Ref</span> : <span class="Apple-converted-space">  </span><span class="s1">this</span>.dereference()</p>
107 <p class="p10"><br></p>
108 <p class="p5">5.value.postln;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></p>
109 <p class="p5">{ 5.squared }.value.postln;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></p>
110 <p class="p5"><span class="s1">Ref</span>.new(123).value.postln;</p>
111 <p class="p12"><br></p>
112 <p class="p5">5.dereference.postln;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></p>
113 <p class="p5">{ 5.squared }.dereference.postln;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></p>
114 <p class="p5"><span class="s1">Ref</span>.new(123).dereference.postln;</p>
115 <p class="p11"><br></p>
116 <p class="p11"><br></p>
117 <p class="p3">Yet another example of polymorphism is <b>play</b>. Many different kinds of objects know how to play themselves.</p>
118 <p class="p11"><br></p>
119 <p class="p5">{ <span class="s1">PinkNoise</span>.ar(0.1) }.play;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s4">// Function</span></p>
120 <p class="p10"><br></p>
121 <p class="p5">(<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s4">// AppClock</span></p>
122 <p class="p5"><span class="s1">var</span> w, r;</p>
123 <p class="p5">w = <span class="s1">Window</span>.new(<span class="s5">"trem"</span>, <span class="s1">Rect</span>(512, 256, 360, 130));</p>
124 <p class="p5">w.front;</p>
125 <p class="p5">r = <span class="s1">Routine</span>({ <span class="s1">arg</span> appClockTime;</p>
126 <p class="p13"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>[</span>"AppClock has been playing for secs:"<span class="s2">,appClockTime].postln;</span></p>
127 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>60.do({ <span class="s1">arg</span> i;</p>
128 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>0.05.yield;</p>
129 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>w.bounds = w.bounds.moveBy(10.rand2, 10.rand2);</p>
130 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>w.alpha = cos(i*0.1pi)*0.5+0.5;</p>
131 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>});</p>
132 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>1.yield;</p>
133 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>w.close;</p>
134 <p class="p5">});</p>
135 <p class="p5"><span class="s1">AppClock</span>.play(r);</p>
136 <p class="p5">)</p>
137 <p class="p10"><br></p>
138 <p class="p5">(<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s4">// SynthDef</span></p>
139 <p class="p13"><span class="s2">x = </span><span class="s1">SynthDef</span><span class="s2">(</span>"Help-SynthDef"<span class="s2">,<span class="Apple-converted-space"> </span></span></p>
140 <p class="p5"><span class="Apple-tab-span"> </span>{ <span class="s1">arg</span> out=0;</p>
141 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">Out</span>.ar(out, <span class="s1">PinkNoise</span>.ar(0.1))</p>
142 <p class="p5"><span class="Apple-tab-span"> </span>}).play;</p>
143 <p class="p5">)</p>
144 <p class="p10"><br></p>
145 <p class="p5"><span class="s1">Pbind</span>(<span class="s3">\degree</span>, <span class="s1">Pseq</span>([0, 1, 2, 3],<span class="s1">inf</span>)).play;<span class="Apple-tab-span"> </span><span class="s4">// Pattern</span></p>
146 <p class="p10"><br></p>
147 <p class="p2"><br></p>
148 <p class="p3">Polymorphism allows you to write code that does not assume anything about the implementation of an object, but rather asks the object to "do what I mean" and have the object respond appropriately.</p>
149 <p class="p2"><br></p>
150 </body>
151 </html>