Polymorphism: Difference between revisions

Added FreeBASIC
(Added FreeBASIC)
 
(6 intermediate revisions by 3 users not shown)
Line 1,389:
 
=={{header|Elena}}==
ELENA 56.0x :
<syntaxhighlight lang="elena">import extensions;
class Point
{
prop int X : prop;
prop int Y : prop;
constructor new(int x, int y)
Line 1,411:
class Circle : Point
{
prop int R : prop;
constructor new()
Line 1,420:
constructor new(int x, int y, int r)
<= super new(x, y)
{
R := r
Line 1,807:
 
end program inh
 
</syntaxhighlight>
 
=={{header|FreeBASIC}}==
FreeBASIC does not support object-oriented programming, so we will use a more procedural approach.
<syntaxhighlight lang="vbnet">Type PPoint
x As Integer
y As Integer
End Type
 
Type CCircle
p As PPoint
r As Integer
End Type
 
Sub PointInit (pthis As PPoint Ptr, x0 As Integer, y0 As Integer)
pthis->x = x0
pthis->y = y0
End Sub
 
Sub CircleInit (pthis As CCircle Ptr, x0 As Integer, y0 As Integer, r0 As Integer)
pthis->p.x = x0
pthis->p.y = y0
pthis->r = r0
End Sub
 
Sub PointPrint (pthis As PPoint Ptr)
Print "Point at (" & pthis->x & ", " & pthis->y & ")"
End Sub
 
Sub CirclePrint (pthis As CCircle Ptr)
Print "Circle at center(" & pthis->p.x & ", " & pthis->p.y & "), radius " & pthis->r
End Sub
 
Dim As Integer i
Dim As PPoint points(3)
Dim As CCircle circles(4)
 
For i = 0 To 3
PointInit(@points(i), i, i+1)
PointPrint(@points(i))
Next
 
For i = 0 To 4
CircleInit(@circles(i), i, i+1, i+2)
CirclePrint(@circles(i))
Next
 
Sleep</syntaxhighlight>
{{out}}
<pre>Point at (0, 1)
Point at (1, 2)
Point at (2, 3)
Point at (3, 4)
Circle at center(0, 1), radius 2
Circle at center(1, 2), radius 3
Circle at center(2, 3), radius 4
Circle at center(3, 4), radius 5
Circle at center(4, 5), radius 6</pre>
 
=={{header|Go}}==
Line 2,423 ⟶ 2,479:
Circle at center (5, 6), radius 8
</pre>
 
=={{header|Logtalk}}==
 
Logtalk is a declarative form of OOP, not imperative, so many of the requirements of the task, while hypothetically being possible in Logtalk, are not going to be native idioms in it and will lead to code that is hard to read, reason about, and maintain (as they, indeed, do in imperative OOP). As such the notion of "copy constructor" and other stateful issues will not be addressed.
 
Logtalk supports both prototypal OOP as well as classical OOP. This example illustrates the prototypal solution as it is the most straightforward. It also uses the notion of parametric objects as a more natural way of expressing the relationship. The advantages of such will be explained in a later example.
 
=== <code>shapes.lgt</code> ===
 
<syntaxhighlight lang="logtalk">:- object(point(_X_, _Y_)).
 
:- public([x/1, y/1, print/0]).
x(_X_).
y(_Y_).
 
print :- logtalk::print_message(information, shapes, @point(_X_,_Y_)).
 
:- end_object.
 
:- object(circle(_X_, _Y_, _R_),
extends(point(_X_, _Y_))).
 
:- public([r/1]).
r(_R_).
 
print :- logtalk::print_message(information, shapes, @circle(_X_,_Y_,_R_)).
 
:- end_object.</syntaxhighlight>
 
In the following output, any text after <code>%%</code> is a pedagogical comment and does not show up in the actual output. Running from the Logtalk toplevel:
 
{{out}}
<pre>
%% First we bring in the shapes code.
?- logtalk_load(shapes). %% or `{shapes}.` in most back-ends.
% [ c:/users/michael t. richter/documents/shapes.lgt loaded ]
% (0 warnings)
true.
 
%% The following is a single query at the toplevel, broken out into multiple lines for clarity.
?- P = point(1, 2), %% `P` is unified with the term `point(1, 2)` (assignment...ish)
| P::print, %% send the `print` message to the object `point(1, 2)`
| P::x(X), %% get the X value of the object `point(1, 2)` by sending the `x` message
| P::y(Y). %% get the Y value of the object `point(1, 2)` by sending the `y` message
% point(1,2) %% output of P::print
P = point(1, 2), %% value of P after executing this query
X = 1, %% value of X after executing this query
Y = 2. %% value of Y after executing this query
 
%% The following is, again, a single query at the toplevel broken out into multiple lines.
%% Only important differences will be noted.
?- C = circle(3, 2, 1), %% `C` is unified with the term `circle(3, 2, 1)`
| C::print,
| C::x(X),
| C::y(Y),
| C::r(R).
% circle(3,2,1) %% circle/3's print method was be called on this message
C = circle(3, 2, 1),
X = 3, %% x/1 and y/1 are called from point/2's implementation to set X and Y
Y = 2,
R = 1. %% R, however, is set from circle/3's implementation
 
%% A shorthand for the first example:
?- P = point(1,2),
| P::(print, x(X), y(Y)).
% point(1,2)
P = point(1, 2),
X = 1,
Y = 2.
 
%% A shorthand for the second example:
?- C = circle(3, 2, 1),
| C::(print, x(X), y(Y), r(R)).
% circle(3,2,1)
C = circle(3, 2, 1),
X = 3,
Y = 2,
R = 1.
</pre>
 
Now consider this source code to illustrate some of the features of this implementation of shapes.
 
=== <code>shapes_demo.lgt</code> ===
 
<syntaxhighlight lang="logtalk">point(1, 2).
point(3, 4).
point(5, 6).
 
circle(30, 20, 10).
circle(40, 30, 20).
circle(50, 40, 30).</syntaxhighlight>
 
Here we have merely supplied a set of "facts": simple term assertions. These are not objects. These are not constructor calls. They are simply declarative statements in Logtalk (which in this case operate as in native Prolog).
 
Continuing from the toplevel:
 
{{out}}
<pre>
%% Bring in the `shapes_demo.lgt` code.
?- {shapes_demo}. %% or `logtalk_load(shapes_demo).`
 
%% Showing that these are just Prolog facts.
?- point(X, Y).
X = 1,
Y = 2 ;
X = 3,
Y = 4 ;
X = 5,
Y = 6.
 
?- circle(X, Y, R).
X = 30,
Y = 20,
R = 10 ;
X = 40,
Y = 30,
R = 20 ;
X = 50,
Y = 40,
R = 30.
</pre>
 
Why does this matter? Because in Logtalk terms can be proxies for parametric objects using the <code>{...}</code> operator. Combining with the shortcut <code>(...)</code> syntax demonstrated earlier:
 
<pre>
%% For each point, bind consecutively with X and Y.
?- {point(_, _)}::(x(X), y(Y)).
X = 1,
Y = 2 ;
X = 3,
Y = 4 ;
X = 5,
Y = 6.
 
%% For each circle, print the circle contents and bind the radius.
?- {circle(_, _, _)}::(print, r(R)).
% circle(30,20,10)
R = 10 ;
% circle(40,30,20)
R = 20 ;
% circle(50,40,30)
R = 30.
</pre>
 
Here we can see that although the contents of <code>shapes_demo.lgt</code> is only a database of simple (Prolog) facts, those facts can, in fact, be iterated over using backtracking and be treated as Logtalk objects. When queried as proxies, the facts __did not have parameter bindings__. (<code>_</code> is the "don't care; don't bind" parameter in Prolog and Logtalk.) Yet we were still able to treat them as the objects in question, sending the messages and binding to their parameterized values through the object code.
 
=={{header|Lua}}==
Line 4,610 ⟶ 4,811:
 
The following program uses the same examples as the Kotlin entry.
<syntaxhighlight lang="ecmascriptwren">class Point {
construct new(x, y) {
_x = x
2,122

edits