Polymorphic copy: Difference between revisions

m
→‎{{header|Phix}}: added syntax colouring the hard way
(Updated to work with Nim 1.4: replaced TObject with RootObj; added {.base.} on method "speak" for type T. Minor changes in text.)
m (→‎{{header|Phix}}: added syntax colouring the hard way)
Line 1,669:
 
For this demonstration (not that this really proves much), our types T and S (overkill really) are just going to contain a string name and a method (routine_id).
<lang Phix>enum NAME, METHOD
 
<!--<lang Phix>-->
procedure me_t()
<span style="color: #008080;">enum</span> <span style="color: #000000;">NAME</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">METHOD</span>
puts(1,"I is a T\n")
end procedure
<span style="color: #008080;">procedure</span> <span style="color: #000000;">me_t</span><span style="color: #0000FF;">()</span>
constant r_t = routine_id("me_t")
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"I is a T\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">me_s</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"I is an S\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">type</span> <span style="color: #000000;">T</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">o</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- as o[METHOD] can be overidden, don't verify it (as in test for me_t)!</span>
<span style="color: #008080;">return</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">2</span> <span style="color: #008080;">and</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">[</span><span style="color: #000000;">NAME</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">and</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">[</span><span style="color: #000000;">METHOD</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
<span style="color: #008080;">type</span> <span style="color: #000000;">S</span><span style="color: #0000FF;">(</span><span style="color: #000000;">T</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">METHOD</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">me_s</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
<span style="color: #000000;">S</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"S"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">me_s</span><span style="color: #0000FF;">}</span>
<span style="color: #000000;">T</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"T"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">me_t</span><span style="color: #0000FF;">}</span>
<span style="color: #7060A8;">call_proc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">METHOD</span><span style="color: #0000FF;">],{})</span>
<span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span>
<span style="color: #7060A8;">call_proc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">METHOD</span><span style="color: #0000FF;">],{})</span>
<!--</lang>-->
 
procedure me_s()
puts(1,"I is an S\n")
end procedure
constant r_s = routine_id("me_s")
 
type T(object o)
-- as o[METHOD] can be overidden, don't verify it!
return sequence(o) and length(o)=2 and string(o[NAME]) and integer(o[METHOD])
end type
 
type S(T t)
return t[METHOD] = r_s
end type
 
S this = {"S",r_s}
T that = {"T",r_t}
 
call_proc(that[METHOD],{})
that = this
call_proc(that[METHOD],{})</lang>
{{out}}
<pre>
Line 1,706 ⟶ 1,708:
Note the result from get_struct_fields() is not documented and liable to change between releases.<br>
The deep_copy routine also shows how to break privacy on fetch/set of private fields by faking the context (name).
<lang Phix>include builtins/structs.e
 
function deep_copy(class c)
string name = get_struct_name(c)
class res = new(name)
sequence fields = get_struct_fields(c)
for i=1 to length(fields) do
string field = fields[i][1]
store_field(res,field,fetch_field(c,field,name),name)
end for
return res
end function
 
<!--<lang Phix>-->
class T
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">/</span><span style="color: #000000;">structs</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
private atom x
public atom y
<span style="color: #008080;">function</span> <span style="color: #000000;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #008080;">class</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
procedure show()
<span style="color: #004080;">string</span> <span style="color: #000000;">name</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_struct_name</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
printf(1,"This is T%d/%d\n",{x,y})
<span style="color: #008080;">class</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">(</span><span style="color: #000000;">name</span><span style="color: #0000FF;">)</span>
end procedure
<span style="color: #004080;">sequence</span> <span style="color: #000000;">fields</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_struct_fields</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
end class
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fields</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">field</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fields</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">store_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">field</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fetch_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">field</span><span style="color: #0000FF;">,</span><span style="color: #000000;">name</span><span style="color: #0000FF;">),</span><span style="color: #000000;">name</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">class</span> <span style="color: #000000;">T</span>
<span style="color: #008080;">private</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">x</span>
<span style="color: #008080;">public</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">y</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">show</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"This is T%d/%d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">class</span>
<span style="color: #000000;">T</span> <span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">({</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}),</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">s</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">3</span>
<span style="color: #000000;">t</span><span style="color: #0000FF;">.</span><span style="color: #000000;">show</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">s</span><span style="color: #0000FF;">.</span><span style="color: #000000;">show</span><span style="color: #0000FF;">()</span>
<!--</lang>-->
 
T t = new({1,2}),
s = deep_copy(t)
s.y = 3
t.show()
s.show()</lang>
{{out}}
<pre>
7,820

edits