Polymorphism: Difference between revisions
Added FreeBASIC
(Added FreeBASIC) |
|||
(44 intermediate revisions by 18 users not shown) | |||
Line 7:
=={{header|ActionScript}}==
<
{
public class Point
Line 45:
}
}
}</
<
public class Circle extends Point
{
Line 72:
}
}
}</
=={{header|Ada}}==
This example is constructed using a parent package and a child package. The parent package defines the Point type. The child package defines the Circle type.
<
type Point is tagged private;
procedure Print(Item : in Point);
Line 92:
Y : Integer := 0;
end record;
end Shapes;</
<
package body Shapes is
Line 169:
end Create;
end Shapes;</
The following is the child package defining the Circle type.
<
type Circle is new Point with private;
procedure Print(Item : Circle);
Line 188:
R : Integer := 0;
end record;
end Shapes.Circles;</
<
package body Shapes.Circles is
Line 294:
end Create;
end Shapes.Circles;</
The following procedure is an entry point for a program, serving the same purpose as the main function in C.
<
use Shapes;
Line 305:
P.Print;
C.Print;
end Shapes_Main;</
=={{header|Aikido}}==
<
class Point (protected x=0.0, protected y=0.0) {
public function print {
Line 335:
c.print()
</syntaxhighlight>
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|Any - tested with release 2.8.win32}}
<
# define the CIRCLE and POINT modes #
Line 433:
PRINT c1; newline( stand out )
END</
{{out}}
<pre>
Line 439:
Circle(+4.10000000000000e +0 @ +0.00000000000000e +0,+0.00000000000000e +0)
</pre>
=={{header|Arturo}}==
<syntaxhighlight lang="rebol">define :point [x,y][
init: [
ensure -> is? :floating this\x
ensure -> is? :floating this\y
]
print: [
render "point (x: |this\x|, y: |this\y|)"
]
]
define :circle [center,radius][
init: [
ensure -> is? :point this\center
ensure -> is? :floating this\radius
]
print: [
render "circle (center: |this\center|, radius: |this\radius|)"
]
]
p: to :point [10.0, 20.0]
c: to :circle @[p, 10.0]
inspect p
inspect c
print p
print c</syntaxhighlight>
{{out}}
<pre>[ :point
x : 10.0 :floating
y : 20.0 :floating
]
[ :circle
center : [ :point
x : 10.0 :floating
y : 20.0 :floating
]
radius : 10.0 :floating
]
point (x: 10.0, y: 20.0)
circle (center: point (x: 10.0, y: 20.0), radius: 10.0)</pre>
=={{header|AutoHotkey}}==
{{works with|AutoHotkey 1.1}}
AutoHotkey does not support private or protected properties and thus does not need assignment and accessor methods. Assignment and accessor methods, as well as direct assignment and access, are shown. For more information see [http://ahkscript.org/docs/Objects.htm Objects].
<
MyPoint.Print()
MyCircle := new Circle(4, 7, 9)
Line 515 ⟶ 564:
this.r := aValue
}
}</
=={{header|BASIC}}==
Line 522 ⟶ 571:
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<
REM Create parent class with void 'doprint' method:
Line 559 ⟶ 608:
PROC(mycircle.doprint)
PROC_discard(mycircle{})
END</
{{out}}
<pre>
Line 569 ⟶ 618:
* See [[Polymorphism/C]]
=={{header|C
<syntaxhighlight lang="csharp">using System;
class Point
{
protected
public Point() : this(0) {}
public Point(int x) : this(x,0) {}
public Point(int x, int y) { this.x = x; this.y = y; }
public int X { get { return x; } set { x = value; } }
public int Y { get { return y; } set { y = value; } }
public virtual void print() { System.Console.WriteLine("Point"); }
}
public class Circle : Point
{
private int r;
public Circle(Point p) : this(p,0) { }
public Circle(Point p, int r) : base(p) { this.r = r; }
public Circle() : this(0) { }
public Circle(int x) : this(x,0) { }
public Circle(int x, int y) : this(x,y,0) { }
public Circle(int x, int y, int r) : base(x,y) { this.r = r; }
public int R { get { return r; } set { r = value; } }
public override void print() { System.Console.WriteLine("Circle"); }
public static void main(String args[])
{
Point p = new Point();
Point c = new Circle();
p.print();
c.print();
}
}</syntaxhighlight>
=={{header|C++}}==
<syntaxhighlight lang="cpp">#include <cstdio>
#include <cstdlib>
class Point {
protected:
int x, y;
public:
Point(int x0 = 0, int y0 = 0) : x(x0), y(y0) {}
Point(const Point
virtual ~Point() {}
const Point& operator=(const Point
if (this != &p) {
}
int getX() { return x; }
int getY() { return y; }
virtual void print() { printf("Point\n"); }
};
class Circle
private:
int r;
public:
Circle(Point p, int r0 = 0) : Point(p), r(r0) {}
Circle(int x0 = 0, int y0 = 0, int r0 = 0) : Point(x0, y0), r(r0) {}
virtual ~Circle() {}
const Circle& operator=(const Circle
if (this != &c) {
}
int getR() { return r; }
virtual void print() { printf("Circle\n"); }
};
int main() {
Point *p = new Point();
Point *
delete p;
return EXIT_SUCCESS;
}</syntaxhighlight>
'''Pattern:''' [[CRTP|Curiously Recurring Template Pattern]]
<syntaxhighlight lang="cpp">#include <cstdio>
#include <cstdlib>
// CRTP: Curiously Recurring Template Pattern
template <typename Derived>
class PointShape
Line 643 ⟶ 730:
// compile-time virtual function
void print() const { reinterpret_cast<const Derived*>(this)->printType(); }
};
Line 661 ⟶ 748:
return *this;
}
void printType() const { printf("Point\n"); }
};
Line 670 ⟶ 757:
public:
Circle(int x0 = 0, int y0 = 0, int r0 = 0) : PointShape(x0, y0), r(r0) { }
Circle(Point p, int r0 = 0) : PointShape(p.
~Circle() {}
const Circle& operator=(const Circle& c)
Line 683 ⟶ 770:
}
int getR() { return r; }
void printType() const { printf("Circle\n"); }
};
int main()
{
PointShape<Point>* p = new Point();
p->print();
c->print();
delete p;
delete c;
return 0;
}</
=={{header|
<syntaxhighlight lang="ceylon">import ceylon.language {
consolePrint = print
}
shared void run() {
class Point {
shared variable Integer x;
shared variable Integer y;
}
shared new copy(Point p) {
this.x = p.x;
consolePrint("[Point ``x`` ``y``]");
}
}
class Circle extends Point {
shared variable Integer r;
shared new(Integer x = 0, Integer y = 0, Integer r = 0) extends Point(x, y) {
this.r = r;
}
shared new copy(Circle c) extends Point.copy(c){
this.r = c.r;
}
shared actual void print() {
consolePrint("[Circle ``x`` ``y`` ``r``]");
}
}
value shapes = [
Point(), Point(1), Point(1, 2), Point {y = 3;}, Point.copy(Point(4, 5)),
Circle(), Circle(1), Circle(2, 3), Circle(4, 5, 6), Circle {y = 7; r = 8;}, Circle.copy(Circle(9, 10, 11))
];
for(shape in shapes) {
shape.print();
}
}
</syntaxhighlight>
=={{header|Clojure}}==
Clojure 1.2.
<
(print-it [this] "Prints out the Printable."))
Line 750 ⟶ 860:
(defn create-circle
"Redundant consturctor function."
[x y r] (Circle. x y r))</
=={{header|Common Lisp}}==
<
((x :initarg :x :initform 0 :accessor x)
(y :initarg :y :initform 0 :accessor y)))
Line 775 ⟶ 885:
(c (make-instance 'circle :radius 5)))
(print-shape p)
(print-shape c))</
=={{header|D}}==
<
class Point {
Line 813 ⟶ 923:
writeln(p);
writeln(c);
}</
=={{header|Delphi}}==
<
{ TPoint }
Line 922 ⟶ 1,032:
begin
ShowMessage('MyPoint');
end;</
<
MyPoint: TMyPoint;
Circle: TCircle;
Line 940 ⟶ 1,050:
FreeAndNil(MyPoint);
end;
end;</
=={{header|E}}==
<
def point implements pbc {
to __printOn(out) { out.print(`<point $x,$y>`) }
Line 965 ⟶ 1,075:
}
return circle
}</
(It is unidiomatic to have mutation operations on an object of this sort in E, so this example has variation operations instead. __optUncall is used for serialization, and is the closest analogue to a copy constructor. E does not have destructors, but only post-mortem finalizers (which are registered after the object is created). The "extends" is only implementation inheritance; it is not necessary to enable polymorphism.)
<
def c := makeCircle(1, 1, 2)
println(p)
println(c)</
=={{header|EchoLisp}}==
<
(struct Point ((real:x 0) (real:y 0)))
(struct Circle ((real:x 0) (real:y 0) (real:r 1)))
Line 1,018 ⟶ 1,128:
(print (Circle 0 0 10))
→ ⭕️ center:[0 0] radius:10 diameter:62.83185307179586
</syntaxhighlight>
=={{header|Eiffel}}==
<
POINT
inherit
Line 1,085 ⟶ 1,195:
Result := "Point: x = " + x.out + " y = " + y.out
end
end</
<
CIRCLE
Line 1,168 ⟶ 1,278:
non_negative_radius: r >= 0
end</
<
APPLICATION
Line 1,204 ⟶ 1,314:
end
end</
{{out}}
Line 1,227 ⟶ 1,337:
Solution of this problem in Ela is similar to Haskell, as soon as Ela shares with Haskell the same features - namely, classes (typeclasses) and algebraic types.
<
instance Show Point where
Line 1,269 ⟶ 1,379:
circleZ = Circle 0 0
circleEmpty = Circle 0 0 0</
Class Show is defined in prelude and is effectively an abstraction for all "printable" entities.
Line 1,275 ⟶ 1,385:
Normally, algebraic types are analyzed using pattern matching, however, it is possible to provide a support for an "accessor style" approach by providing an instance for class Name (which is also defined in prelude). With this instance it is possible to write code like so:
<
c.x //Evaluates to 12</
=={{header|Elena}}==
ELENA 6.x :
<syntaxhighlight lang="elena">import extensions;
class Point
{
int X : prop;
int Y : prop;
constructor new(int x, int y)
{
X := x;
Y := y
}
constructor new()
<= new(0,0);
print() { console.printLine("Point") }
}
class Circle : Point
{
int R : prop;
constructor new()
<= new(0);
constructor new(int r)
<= new(0, 0, r);
constructor new(int x, int y, int r)
<= super new(x, y)
{
R := r
}
print() { console.printLine("Circle") }
}
public program()
{
Point p := Point.new();
Point c := Circle.new();
p.print();
c.print()
}</syntaxhighlight>
{{out}}
<pre>
Point
Circle
</pre>
=={{header|EMal}}==
<syntaxhighlight lang="emal">
type Point
fun default = Point by block do return Point(0, 0) end
fun copy = Point by Point p do return Point(p.getX(), p.getY()) end
fun byX = Point by int x do return Point(x, 0) end
fun byCoords = Point by int x, int y do return Point(x, y) end
model
int x, y
new by int x, int y
me.x = x
me.y = y
end
fun getX = int by block do return me.x end
fun setX = void by int x do me.x = x end
fun getY = int by block do return me.y end
fun setY = void by int y do me.y = y end
fun print = void by block
writeLine("I am a Point at (" + me.x + "," + me.y + ")")
end
end
type Circle extends Point
fun default = Circle by block do return Circle(0, 0, 0) end
fun copy = Circle by Circle c do return Circle(c.getX(), c.getY(), c.getR()) end
fun byCenterAndRadius = Circle by Point p, int r do return Circle(p.getX(), p.getY(), r) end
fun byCoordsAndRadius = Circle by int x, int y, int r do return Circle(x, y, r) end
model
int r
new by int x, int y, int r :base(x, y)
me.r = r
end
fun getR = int by block do return me.r end
fun setR = void by int x do me.r = r end
fun print = void by block
writeLine("I am a Circle with center at (" + me.x + "," + me.y + ") and radius is " + me.r)
end
end
type Main
Point.default().print()
Point.copy(Point(32, 32)).print()
Point.byCoords(20, 20).print()
Point.byX(10).print()
Circle.default().print()
Circle.copy(Circle(18, 18, 6)).print()
Circle.byCoordsAndRadius(10, 10, 5).print()
Circle.byCenterAndRadius(Point(7, 7), 4).print()
Point p = Point(20, 20)
Point c = Circle(10, 10, 5)
Circle c1 = c
p.print()
c.print()
watch(p)
watch(c)
watch(c1)
</syntaxhighlight>
{{out}}
<pre>
I am a Point at (0,0)
I am a Point at (32,32)
I am a Point at (20,20)
I am a Point at (10,0)
I am a Circle with center at (0,0) and radius is 0
I am a Circle with center at (18,18) and radius is 6
I am a Circle with center at (10,10) and radius is 5
I am a Circle with center at (7,7) and radius is 4
I am a Point at (20,20)
I am a Circle with center at (10,10) and radius is 5
Point: <§(0x02bf8098)>
Point, Circle: <§(0x00bb8560)>
Circle: <§(0x00bb8560)>
</pre>
=={{header|F Sharp|F#}}==
Polymorphism is achieved by defining an interface <code>Printable</code> which is implemented by <code>Point</code> and <code>Circle</code>. (In real code, you should override the <code>ToString</code> method which every class inherits from <code>Object</code>.)
Due to the use of optional parameters, we only need one constructor for every class. No accessors are necessary because we use public read-only properties. (Mutable properties are possible, too, but should be avoided in idiomatic code.)
<syntaxhighlight lang="fsharp">type Printable =
abstract member Print : unit -> unit
type Point(?x, ?y) =
member t.x = defaultArg x 0.0
member t.y = defaultArg y 0.0
interface Printable with
member t.Print() = printfn "Point(x:%f, y:%f)" t.x t.y
type Circle(?center, ?radius) =
member t.center = defaultArg center (new Point())
member t.radius = defaultArg radius 1.0
interface Printable with
member t.Print() =
printfn "Circle(x:%f, y:%f, r:%f)" t.center.x t.center.y t.radius</syntaxhighlight>
=={{header|Factor}}==
<
GENERIC: print ( shape -- )
Line 1,291 ⟶ 1,548:
C: <circle> circle
M: circle print drop "Circle" io:print ;</
=={{header|Forth}}==
{{works with|4tH|3.62.0}}
There are numerous, mutually incompatible object oriented frameworks for Forth. This one works with the FOOS preprocessor extension of [[4tH]]. Variadic functions in Forth are usually implemented by passing the number of parameters. Since it is highly unlikely that objects are allocated that low in memory it works. Note that X, Y and Z are passed in reverse order, which is quite common for any Forth program.
<
include 4pp/lib/foos.4pp
Line 1,384 ⟶ 1,641:
Circle2 => print
Circle1 new Circle Circle3
Circle3 => print</
Works with any ANS Forth
Needs
https://github.com/DouglasBHoffman/FMS2
<
:class point
cell bytes x
cell
;class
23 5 point p
p print
p copy dup print <free
:class circle <super point
cell bytes r
:m print super print r ? ;m
:m get ( -- x y r) super get r @ ;m
:m copy ( --
;class
4 5 2 circle c
c print
c copy dup print <free </syntaxhighlight>
=={{header|Fortran}}==
Fortran provides OO features with the type mechanism. This example works with the Intel 11.1.069 compiler.
<
module geom
Line 1,574 ⟶ 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}}==
<
import "fmt"
Line 1,678 ⟶ 1,947:
}
// Destructors are never used in Go. Objects are garbage collected.</
=={{header|Golo}}==
<syntaxhighlight lang="golo">#!/usr/bin/env golosh
----
This module demonstrates Golo's version of polymorphism.
----
module Polymorphism
# Each struct automatically gets a constructor and also accessor and assignment methods for each field.
# For example, the constructor for Point is Point(1, 2)
# and the accessor methods are x() and y()
# and the assignment methods are x(10) and y(10).
struct Point = { x, y }
struct Circle = { x, y, r }
# Augmentations are the way to give your struct methods.
# They're like extension methods in C# or Xtend.
augment Point {
function print = |this| { println("Point " + this: x() + " " + this: y()) }
}
augment Circle {
function print = |this| { println("Circle " + this: x() + " " + this: y() + " " + this: r()) }
}
# You can define functions with the same name as your struct that work
# basically like constructors.
----
A contructor with no arguments that initializes all fields to 0
----
function Point = -> Point(0, 0)
----
This is the copy constructor when the argument is another point
----
function Point = |x| -> match {
when x oftype Point.class then Point(x: x(), x: y())
otherwise Point(x, 0)
}
----
A contructor with no arguments that initializes all fields to 0
----
function Circle = -> Circle(0, 0, 0)
----
This is the copy constructor when the argument is another circle
----
function Circle = |x| -> match {
when x oftype Circle.class then Circle(x: x(), x: y(), x: r())
otherwise Circle(x, 0, 0)
}
----
This one initializes the radius to zero
----
function Circle = |x, y| -> Circle(x, y, 0)
function main = |args| {
let p = Point(10, 20)
let c = Circle(10, 20, 30)
let shapes = vector[
Point(), Point(1), Point(1, 2), Point(p),
Circle(), Circle(1), Circle(1, 2), Circle(1, 2, 3), Circle(c)
]
foreach shape in shapes {
shape: print()
}
}</syntaxhighlight>
=={{header|Groovy}}==
<
@TupleConstructor(force = true)
@ToString(includeNames = true)
Line 1,698 ⟶ 2,042:
void print() { println toString() }
Number r
}</
Test Code:
<
def c = new Circle(x: 4, y: 3, r: 5)
Line 1,707 ⟶ 2,051:
v2.print()
assert v1 == v2
}</
{{out}}
<pre>Verifying Point(x:3, y:4) == Point(x:3, y:4)
Line 1,715 ⟶ 2,059:
Polymorphism is achieved through the type class Show
<
instance Show Point where
show (Point x y) = "Point at "++(show x)++","++(show y)
Line 1,745 ⟶ 2,089:
--Constructor that sets x and r to 0
c0OnYAxis = flip (Circle 0) 0</
== Icon and {{header|Unicon}} ==
Line 1,753 ⟶ 2,097:
There is no destructor, as Unicon manages object destruction itself. The copy constructor is emulated by a method. Notice the 'initially' clauses. These act like constructors, in that they accept input parameters during instance construction. These parameters are null if not used, and so the initial field values are set to 0 if the entered value is null (tested using the '/' symbol).
<
# make a new copy of this instance
method copy ()
Line 1,816 ⟶ 2,160:
c4.print ()
end
</syntaxhighlight>
=={{header|Inform 7}}==
Line 1,822 ⟶ 2,166:
Accessors are not needed since property values are public. Constructors and destructors are not needed since objects are statically allocated and initialized.
<
A point is a kind of thing.
Line 1,840 ⟶ 2,184:
print the origin;
print the circle of power;
end the story.</
=={{header|J}}==
<
create=: monad define
'X Y'=:2{.y
Line 1,855 ⟶ 2,199:
smoutput 'Point ',":X,Y
)
destroy=: codestroy</
<
coinsert 'Point'
create=: monad define
Line 1,866 ⟶ 2,210:
print=: monad define
smoutput 'Circle ',":X,Y,R
)</
=={{header|Java}}==
<
protected int x, y;
public Point() { this(0); }
Line 1,904 ⟶ 2,248:
c.print();
}
}</
=={{header|JavaScript}}==
<
* var p = new Point(x,y);
* var p = new Point(a_point);
Line 1,969 ⟶ 2,313:
var out = "Circle(" + this.x + "," + this.y + "," + this.r + ")";
print(out);
}</
=={{header|jq}}==
<syntaxhighlight lang="jq">
def Point(x;y): {"type": "Point", "x": x, "y": y};
def Point(x): Point(x;0);
def Point: Point(0);
def Circle(x;y;r): {"type": "Circle", "x": x, "y": y, "r": r};
def Circle(x;y): Circle(x;y;0);
def Circle(x): Circle(x;0);
def Circle: Circle(0);
def print:
if .type == "Circle" then "\(.type)(\(.x); \(.y); \(.r))"
elif .type == "Point" then "\(.type)(\(.x); \(.y))"
else empty
end;
</syntaxhighlight>
In practice, it's unlikely one would want to write accessors, as .x will retrieve "x", etc; similar remarks apply to setters (.x = VALUE). `.` will copy, and `empty` could serve as a kind of destructor, in that `Point(0;0) | empty` produces the empty stream.
For the sake of illustration, one could define a polymorphic "setter" as follows:
<syntaxhighlight lang="jq">
# keyname should be (or evaluate to) a string
def set(keyname; value):
if type == "object" and .type and has(keyname) then .[keyname] = value
else error("set: invalid type: \(.)")
end;
</syntaxhighlight>
Example:
<syntaxhighlight lang="julia">
Circle(0;1;2) | .x = 1 | print
</syntaxhighlight>
=={{header|Julia}}==
There is no obvious inheritance hierarchy here to get polymorphism. Julia has multiple dispatch, so the appropriate implementation of the
It would not be idiomatic to define setters and getters for a type like this in Julia. One would just access the fields directly. There is no need to explicitly define a constructor since that is automatically provided. You only roll your own if you need more elaborate initialization or you need to set default values.
{{works with|Julia|0.6}}
<syntaxhighlight lang="julia">mutable struct Point
x::Float64
y::Float64
end
setx(p::Point, x) = (p.x = x)
sety(p::Point, y) = (p.y = y)
x::Float64
y::Float64
Line 1,999 ⟶ 2,375:
end
setx(c::Circle, x) = (c.x = x)
sety(c::Circle, y) = (c.y = y)
setr(c::Circle, r) = (c.r = r)
=={{header|Kotlin}}==
Line 2,018 ⟶ 2,393:
In the JVM version of Kotlin, it is possible to declare a destructor in the guise of a 'finalize' method though there is no guarantee that this will actually be called by the garbage collector (or, if it is called, when this will be) and consequently many programmers feel it is more trouble than its worth.
<syntaxhighlight lang
open class Point(var x: Int, var y: Int) {
Line 2,038 ⟶ 2,413:
constructor(x: Int) : this(x, 0, 0)
constructor(x: Int, r: Int) : this(x, 0, r)
Line 2,044 ⟶ 2,419:
// for simplicity not calling super.finalize() below though this would normally be done in practice
override protected fun finalize() = println("Finalizing $this...")
override fun toString() = "Circle at center ($x, $y), radius $r"
Line 2,057 ⟶ 2,432:
for (circle in circles) circle.print()
println()
}
fun main(args: Array<String>) {
Line 2,067 ⟶ 2,442:
p.print()
p.y = 7 // change y coordinate
p.print()
val c = Circle(5, 6, 7)
c.print()
c.r = 8
c.print() // change radius
/* note that finalizers for p and c are not called */
}</
{{out}}
Line 2,104 ⟶ 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}}==
Lua does not have a standard definition of objects or classes, so a basic and typical protoctype-based OOP model will be used. In Lua all objects are tables, and through the use of metatables, polymorphism can be achieved in many ways, this is only one of them.
<
local Point = {x = 0, y = 0}
Line 2,135 ⟶ 2,655:
function Circle:copy()
return Circle:new{x = self.x, y = self.y, r = self.r}
end</
=={{header|M2000 Interpreter}}==
For OOP in M2000 we use Groups (we can use COM objects for other reasons, but for OOP we have Groups). A Group is collection of members. We can add permanently or temporary members, but we can't delete (using temporary members, means we delete members, but it isn't the the same as a free delete of any member).
Classes are functions which return groups. Groups are value types, not reference, but we can use pass by reference, for group or for any member (value type plus reference to functions), and also we can use group pointers (pointers can change group which points, references can't change and always reference a named group). We can make a group from other group, just using a =.
Named group means a static group. Float group is a group in a container, like an array item. A pointer to group can be one of two kind, a pointer to named group and a pointer to a float group. A pointer act as container too. A group may have any level of nested groups, and some of them maybe are pointers to groups. References can't be stored, except as strings as weak references, and before use them we have to link again. Pointers which points to named groups has same issue, they use weak reference. A group pointer may change type, to float or to named group, but stay as pointer.
Properties are groups with values inside groups. We can use variables, but properties have a private variable [name] and has a Set and a Value part. We can define properties with Value/Set, Value, Set, or both automatic (here we do that for x,y and r)
We see polymorphism for print method (module in M2000), and for operator "=". Also Constructor in Circle read types of arguments and respond accordingly as programmed. In M2000 we can read arguments later, from stack of values, so we can check this stack.
0~ is single zero. So x, y and r get first value as single type, and stay that. Numeric types can be double (default, no symbol), Decimal (@),Currency(#),Long(&),Integer(%). For Strings we have to use $ in names, for variables and functions. There are groups which have both names, numeric and string, when they return string value. We can make a string property, and interpreter make a group which return/get string. We can add modules/functions to properties, using Group x {...}, inside a group definition (a class has a group definition also).
A Class: label direct interpreter to not include any after in the returned group, a float group, which return a Class function.
A class function is global by default, except in a class definition which is a member of group.
In following examples there is a block for temporary objects. We make a MM as a group, and at the exit of the block, group erased, so next time we make a new one.
Syntax:
<syntaxhighlight lang="m2000 interpreter">
\\ block For This {}, or For object [, object2] { }, where object is a group, or a pointer to group, or an item from an array contains a group
\\ This is "this context".
For This {
\\ any new definition here has a temporary use
\\ can be nested, but if we use object then we can use dots to access members of it. If we use a second one then we have to use double dots (..x for second object, for access to x member)
}
</syntaxhighlight>
<syntaxhighlight lang="m2000 interpreter">
Class PointA {
Property x=0~
Property Y=0~
Operator "=" (n1) {
n=group(n1)
if n.x=.x Then if n.y=.y then push true : exit
push false
}
Module Print {
Print "Point" , .x, .y
}
Class:
Module PointA {
\\ ? means optionally
Read ? .[x], .[y]
}
}
Class Circle {
Property R=300~ ' type single
Operator "=" (n1) {
n=group(n1)
n2=This ' get a copy of this to check n against n2
if valid(@n as n2) else push false :exit
if n.x=.x Then if n.y=.y then if n.r=.r then push true : exit
push false
}
Module Print {
Print "Circle", .x, .y, .r
}
Class:
Module Circle {
if match("nn") then {
M=PointA(Number, Number)
} Else.if match("G") then {
M=PointA()
Read M
} Else M=PointA()
M=This
\\ If match("N") then Read M.r \\ check if a number is in top of stack
\\ Read ? M.r \\ optionally
Read M.r \\ for this example, r has value, so this used if stack is empty.
This=M
}
}
A=PointA(10,3)
C=Circle(20,10,5)
D=Circle(A, 100)
B=A
K=PointA()
Z=Circle(A)
P=PointA(600,700)
\\ N is a pointer to array
N=(A, B, C, D, K, P, Z)
M=each(N)
While M {
For This {
\\ a copy in MM
MM=Array(M)
MM.Print
Print A=MM, D=MM ' using MM=A interpreter use "=" from MM
}
}
\\ pA is a pointer to D (a named group)
pA->D
Print pA=D, pA=Z
pA=>Print
\\ pA is a pointer to a copy of D (a float group)
pA->(D)
Print pA=D, pA=Z
pA=>Print
\\ rA is a reference to D (& is optional in Link statement)
Link &D to &rA
rA.Print
</syntaxhighlight>
Changes for PointA, we use variables, for Circle R has a limit of 1000. We use Stack object, and Inventory for copies of named groups, they changed to float groups.
<syntaxhighlight lang="m2000 interpreter">
Class PointA {
X=0~, Y=0~
Module Print {
Print "Point" , .x, .y
}
Class:
Module PointA {
Read ? .x, .y
}
}
Class Circle {
Property R {
Value,
Set {
If Value>1000 then Value=1000
}
}=300~
Module Print {
Print "Circle", .x, .y, .r
}
Class:
Module Circle {
if match("nn") then {
M=PointA(Number, Number)
} Else.if match("G") then {
M=PointA()
Read M
} Else M=PointA()
M=This
This=M
Read ? .r
}
}
A=PointA(10,3)
C=Circle(20,10,5)
D=Circle(A, 100)
B=A
K=PointA()
Z=Circle(A)
P=PointA(600,700)
\\ N is a pointer to stack
N=Stack:=A, B, C, D, K, P, Z
\\ M is a pointer to an iterator
M=each(N)
While M {
For This {
\\ a copy in MM
MM=StackItem(M)
MM.Print
}
}
\\ NN is a pointer to Inventory
Inventory NN= 1:=A, 2:=B, 3:=C, 4:=D, 5:=K, 6:=P,7:= Z
M=each(NN)
While M {
For This {
\\ a copy in MM
MM=Eval(M)
MM.Print
}
}
\\ we can call NN(3).print
Print "NN(3).Print"
NN(3).Print
NN(3).R=5000
NN(3).Print
</syntaxhighlight>
=={{header|NetRexx}}==
'''Note:''' Based on default values in method prototypes, NetRexx will automatically generate intermediate constructors and methods, thus ensuring that none are omitted.
<
options replace format comments java crossref savelog symbols binary
Line 2,243 ⟶ 2,943:
Rexx(getR()).format(null, 3)')'
return str
</syntaxhighlight>
{{out}}
<pre>
Line 2,261 ⟶ 2,961:
Similar to the Python solution:
<
Point = object
x, y: float
Line 2,295 ⟶ 2,995:
c1.center.x = 12
c1.radius = 5.2</
{{out}}
<pre>p1: (x: 0.0, y: 0.0)
Line 2,301 ⟶ 3,001:
=={{header|Objeck}}==
<
bundle Default {
class Point {
Line 2,384 ⟶ 3,084:
}
}
</syntaxhighlight>
=={{header|Objective-C}}==
<
@interface RCPoint : NSObject {
Line 2,459 ⟶ 3,159:
}
return 0;
}</
=={{header|OCaml}}==
<
object (self)
val mutable x = x
Line 2,494 ⟶ 3,194:
c#set_x 10.0;
print c;
print (new point ~y:2.1 ())</
=={{header|Oforth}}==
Line 2,512 ⟶ 3,212:
<
Point method: initialize(x, y) x := x y := y ;
Point method: _x @x ;
Line 2,525 ⟶ 3,225:
Circle method: << "(" << @x << ", " << @y << ", " << @r << ")" << ;
Circle classMethod: newFromPoint(aPoint, r) self new(aPoint _x, aPoint _y, r) ;</
Usage :
<
| p c |
Point new(3, 4) ->p
Line 2,536 ⟶ 3,236:
c println
System.Out "Attributes of this circle are : " << c _x << ", " << c _y << " and " << c _r << cr
Circle newFromPoint(p, 2) println ;</
{{out}}
Line 2,550 ⟶ 3,250:
ooRexx supports traditional class-based polymorphism. The polymorphic methods can be part of the main class sequence or brought in using mixins for multiple inheritance situations. Here is a simple example using point and circle classes in a hierarchy.
<syntaxhighlight lang="oorexx">
p = .point~new(3,2)
c = .circle~new(,2,6)
Line 2,581 ⟶ 3,281:
say "A circle of radius" radius "centered at location ("||self~x","self~y")"
</syntaxhighlight>
{{out}}
<pre>
Line 2,591 ⟶ 3,291:
Method binding in ooRexx is late and dynamic. In many situations, polymorphism can be achieved merely by providing an expected method. It is not necessary for an object to be of a particular class hierarchy. In the example below, both point and circle implement a print method, but there is no class relationship between these classes other than what they inherit from the object class.
<syntaxhighlight lang="oorexx">
p = .point~new(3,2)
c = .circle~new(,2,6)
Line 2,623 ⟶ 3,323:
say "A circle of radius" radius "centered at location ("||x","y")"
</syntaxhighlight>
{{out}}
<pre>
Line 2,629 ⟶ 3,329:
A circle of radius 6 centered at location (0,2)
</pre>
=={{header|OxygenBasic}}==
Line 2,637 ⟶ 3,336:
A compact format for the methods is used to improve layout.
<
type tpoint float xx,yy
type tcircle float xx,yy,rr
Line 2,694 ⟶ 3,393:
del ca : del cb : del cc
</syntaxhighlight>
=={{header|Oz}}==
Line 2,700 ⟶ 3,399:
No accessors because we use immutable public attributes ("features").
<
feat
x
Line 2,737 ⟶ 3,436:
")"}
end
end</
=={{header|Pascal}}==
Line 2,744 ⟶ 3,443:
=={{header|Perl}}==
What polymorphic function means in the context of Perl is as clear as mud. subs already can take anything as parameter by default. Destructors are automatic, so I dropped them.
<
package Point;
use Class::Spiffy -base;
Line 2,829 ⟶ 3,528:
my $c = Circle->new(r => 4);
print $c->r, "\n"; # accessor autogenerated
}</
=={{header|Phix}}==
===traditional user defined types===
Phix does not enforce object orientation, but is naturally polymorphic. <br>
Destructors are not required, though you can use delete_routine if needed.<br>
Copy constructors are also not required, a plain '=' will do just fine (it uses copy on write semantics).<br>
You could embed routine_ids in the structures to emulate virtual functions.<br>
There are no private members here; for that I would write something that returns integer ids to the outside world.
<!--<syntaxhighlight lang="phix">-->
<span style="color: #008080;">type</span> <span style="color: #000000;">point</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: #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;">atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">and</span> <span style="color: #004080;">atom</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: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">new_point</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</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;">function</span>
<span style="color: #008080;">type</span> <span style="color: #000000;">circle</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: #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: #000000;">point</span><span style="color: #0000FF;">(</span><span style="color: #000000;">o</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">and</span> <span style="color: #004080;">atom</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: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">new_circle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">point</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span> <span style="color: #000080;font-style:italic;">-- assume r got passed in y</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- {point,r}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</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: #000000;">r</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- {point,r}
-- (or {new_point(x,y),r} if you prefer)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000000;">point</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">new_point</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">circle</span> <span style="color: #000000;">c1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">new_circle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">c2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">new_circle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">}</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">c1</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">c2</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
{{4,5},6}
{{4,5},6}
</pre>
===classes===
x, y, and r are private, but appear public because of the presence of getters and setters for them.<br>
There is only a single constructor, but it's parameters can be polymorphic. Note that (obviously) Circle must be tested before Point.<br>
Should you want to invoke the parent class constructor, this.Point(..) should work but is not documented or properly tested.<br>
Destructors are not shown, a procedure ~Point() would work but is not formally documented or guaranteed to be called in a timely fashion, should (eg) print() happen to be hanging on to a reference to it, until you print something else or unless you invoke an explicit delete(''instance'').
{{libheader|Phix/Class}}
<!--<syntaxhighlight lang="phix">-->
<span style="color: #008080;">class</span> <span style="color: #000000;">Point</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">Point</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">Point</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</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: #008080;">else</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #008080;">this</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">get_x</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">return</span> <span style="color: #000000;">x</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">get_y</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">return</span> <span style="color: #000000;">y</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">set_x</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span> <span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">set_y</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span> <span style="color: #008080;">end</span> <span style="color: #008080;">procedure</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;">"point (%g,%g)\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: #008080;">class</span> <span style="color: #000000;">Circle</span> <span style="color: #008080;">extends</span> <span style="color: #000000;">Point</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">r</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">Circle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">Circle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</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: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">.</span><span style="color: #000000;">r</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">Point</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span> <span style="color: #000080;font-style:italic;">-- assume r got passed in y</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</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: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span>
<span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #008080;">this</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">get_r</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">return</span> <span style="color: #000000;">r</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">set_r</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span> <span style="color: #008080;">end</span> <span style="color: #008080;">procedure</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;">"circle (%g,%g,%g)\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: #000000;">r</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;">Point</span> <span style="color: #000000;">p1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">({</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">}),</span>
<span style="color: #000000;">p2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">({</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">p1</span><span style="color: #0000FF;">.</span><span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">7</span>
<span style="color: #000000;">Circle</span> <span style="color: #000000;">c1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">({</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">}),</span>
<span style="color: #000000;">c2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">({</span><span style="color: #000000;">c1</span><span style="color: #0000FF;">}),</span>
<span style="color: #000000;">c3</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">({</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">c1</span><span style="color: #0000FF;">.</span><span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">8</span>
<span style="color: #000000;">p1</span><span style="color: #0000FF;">.</span><span style="color: #000000;">show</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">p2</span><span style="color: #0000FF;">.</span><span style="color: #000000;">show</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">c1</span><span style="color: #0000FF;">.</span><span style="color: #000000;">show</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">c2</span><span style="color: #0000FF;">.</span><span style="color: #000000;">show</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">c3</span><span style="color: #0000FF;">.</span><span style="color: #000000;">show</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
point (4,7)
circle (4,7,8)
circle (4,7,9)
circle (10,11,12)
</pre>
Line 2,904 ⟶ 3,655:
Point class definition.
<syntaxhighlight lang="php">
class Point
{
Line 2,976 ⟶ 3,727:
}
}
</syntaxhighlight>
Circle class definition.
<syntaxhighlight lang="php">
class Circle extends Point
{
Line 3,044 ⟶ 3,795:
}
}
</syntaxhighlight>
Usage:
<syntaxhighlight lang="php">
$point = new Point( 1, 5 );
$circle = new Circle( 1, 5, 6 );
Line 3,061 ⟶ 3,812:
// or
echo $circle;
</syntaxhighlight>
Will result in:
Line 3,069 ⟶ 3,820:
=={{header|PicoLisp}}==
<
# x y
Line 3,087 ⟶ 3,838:
(dm print> ()
(prinl "Circle " (: x) "," (: y) "," (: r)) )</
<
P (new '(+Point) 3 4)
C (new '(+Circle) 10 10 5) )
(print> P)
(print> C)</
{{out}}
<pre>Point 3,4
Line 3,102 ⟶ 3,853:
So it is enough to define classes and the print method.
<
define :class Point;
slot x = 0;
Line 3,120 ⟶ 3,871:
define :method print(p : Circle);
printf('Circle(' >< x(p) >< ', ' >< y(p) >< ', ' >< r(p) >< ')\n');
enddefine;</
To test we can use the following code:
<
lvars instance1 = newPoint();
lvars instance2 = newCircle();
;;; Use print method
print(instance1);
print(instance2);</
=={{header|Prolog}}==
Prolog is not object oriented but polymorphic behaviour is easy to reproduce by replicating predicates for different types.
'classes' are represented by terms (eg: point(x,y), cicle(x,y,z)).
The Copy constructor, assignment and destructor operations are not needed as terms can be copied and assigned using unification as part of the language.
<syntaxhighlight lang="prolog">% Point
point_construct(X, Y, point(X1,Y1)) :-
default(X, X1),
default(Y, Y1).
% Circle
circle_construct(X, Y, R, circle(X1,Y1,R1)) :-
default(X, X1),
default(Y, Y1),
default(R, R1).
% Accessors for general X,Y
% individual getters/setters can be made but it is not required
shape_x_y_set(point(_,_), X, Y, point(X,Y)).
shape_x_y_set(circle(_,_,R), X, Y, circle(X,Y,R)).
% Accessors for R
cicle_r_set(circle(X,Y,_), R, circle(X,Y,R)).
% Print
print_shape(point(X,Y)) :- format('Point (~p,~p)', [X,Y]).
print_shape(circle(X,Y,R)) :- format('Circle (~p,~p,~p)', [X,Y,R]).
% Default values for constructor (default to 0).
default(N, 0) :- var(N).
default(N, N) :- number(N).
% Tests
test_point :-
point_construct(2,3,P),
test_poly(P).
test_circle :-
circle_construct(3,4,_,C),
cicle_r_set(C, 5, C1),
test_poly(C1).
test_poly(T) :-
shape_x_y_set(_, X, Y, T),
X1 is X * 2,
Y1 is Y * 2,
shape_x_y_set(T, X1, Y1, T1),
print_shape(T1).</syntaxhighlight>
{{out}}
<pre>
?- test_point, nl, test_circle, !.
Point (4,6)
Circle (6,8,5)
true.
?-
</pre>
=={{header|PureBasic}}==
Using the open-source precompiler [http://www.development-lounge.de/viewtopic.php?t=5915 SimlpeOOP].
<
BeginProtect
Line 3,191 ⟶ 4,001:
EndMethod
EndClass</
Testcode
<
*circle.Circle = NewObject.Circle
Line 3,201 ⟶ 4,011:
*circle\Print()
CloseConsole()
EndIf</
=={{header|Python}}==
Line 3,209 ⟶ 4,019:
For the print function, use the standard __repr__ methods, used when printing an object. Destructors are not needed of course.
<
def __init__(self, x=0.0, y=0.0):
self.x = x
Line 3,222 ⟶ 4,032:
def __repr__(self):
return '<Circle 0x%x x: %f y: %f radius: %f>' % (
id(self), self.center.x, self.center.y, self.radius)</
Usage example:
Line 3,261 ⟶ 4,071:
Or, using inheritance like some of the other solutions:
<
def __init__(self, x=0.0, y=0.0):
self.x = x
Line 3,274 ⟶ 4,084:
def __repr__(self):
return '<Circle 0x%x x: %f y: %f radius: %f>' % (
id(self), self.x, self.y, self.radius)</
Usage example:
Line 3,315 ⟶ 4,125:
The task calls for the creation of mutable types i.e. that you are allowed to change the values of x, y, or r of a Point or Circle after they have been created.
If this is not needed, then the Python namedtuple is a good way to create immutable classes with named fields such as these.
<
>>> class Point(namedtuple('Point', 'x y')):
def __new__( _cls, x=0, y=0 ):
Line 3,338 ⟶ 4,148:
p.x = 10.81
AttributeError: can't set attribute
>>> </
And if you don't need default arguments, this becomes:
<
>>> Circle = namedtuple('Circle', 'x y r')
>>> Point(3, 4)
Line 3,347 ⟶ 4,157:
>>> Circle(x=1, y=2, r=3)
Circle(x=1, y=2, r=3)
>>> </
=={{header|R}}==
Line 3,353 ⟶ 4,163:
Copy constructors are not needed, since objects are copied by value.
Neither are destructors needed (just use the rm function).
<
representation(
x="numeric",
Line 3,391 ⟶ 4,201:
cat("This is a circle, with radius", x@r, "and centre (", x@centre@x, ",", x@centre@y, ").\n")
})
print(circS4)</
=={{header|Racket}}==
Line 3,397 ⟶ 4,207:
"Fields" come with accessors and mutators for free.
<syntaxhighlight lang="racket">
#lang racket
(define point%
Line 3,412 ⟶ 4,222:
(define/override (custom-write out) (write (show) out))
(define/override (custom-display out) (display (show) out))))
</syntaxhighlight>
{{out}}
<pre>
Line 3,430 ⟶ 4,240:
"<circle% <point% 3 0> 5>"
</pre>
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2020.08.1}}
All appropriate constructors, initializers, accessors, and destructors are provided by default, but may be explicitly declared for flexibility.
To create only readonly accessors for better encapsulation, leave out all the "is rw" traits.
Here we demonstrate that accessors can behave like variables and may be assigned.
<syntaxhighlight lang="raku" line>class Point {
has Real $.x is rw = 0;
has Real $.y is rw = 0;
method Str { $ }
}
class Circle {
has Point $.p is rw = Point.new;
has Real $.r is rw = 0;
method Str { $ }
}
my $c = Circle.new(p => Point.new(x => 1, y => 2), r => 3);
say $c;
$c.p.x = (-10..10).pick;
$c.p.y = (-10..10).pick;
$c.r = (0..10).pick;
say $c;</syntaxhighlight>
In this case we define the Str coercion method polymorphically, which is used by say or print to format the contents of the object.
We could also have defined print methods directly.
We could have factored this method out to a common role and composed it into each class.
We could also have defined multi subs outside of the class, like this:
<syntaxhighlight lang="raku" line>multi print (Point $p) { $p.perl.print }
multi print (Circle $c) { $c.perl.print }</syntaxhighlight>
=={{header|Ruby}}==
Line 3,436 ⟶ 4,277:
The <tt>Kernel#dup</tt> method can be used as a copy constructor.
<
attr_accessor :x,:y
def initialize(x=0, y=0)
Line 3,458 ⟶ 4,299:
"Circle at #{x},#{y} with radius #{r}"
end
end</
Example:
<
puts Point.new # => Point at 0,0
p = Point.new(1, 2)
Line 3,474 ⟶ 4,315:
d.r = 7.5
puts c # => Circle at 4,5 with radius 6
puts d # => Circle at 4,5 with radius 7.5</
=={{header|Scala}}==
{{Out}}Best seen running in your browser either by [https://scalafiddle.io/sf/altUDTl/0 ScalaFiddle (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org/ohfeM4nvTZyeOTYYWHaNgQ Scastie (remote JVM)].
<syntaxhighlight lang="scala">object PointCircle extends App {
class Point(x: Int = 0, y: Int = 0) {
def copy(x: Int = this.x, y: Int = this.y): Point = new Point(x, y)
override def toString = s"Point x: $x, y: $y"
}
object Point {
def apply(x: Int = 0, y: Int = 0): Point = new Point(x, y)
}
case class Circle(x: Int = 0, y: Int = 0, r: Int = 0) extends Point(x, y) {
def copy(r: Int): Circle = Circle(x, y, r)
override def toString = s"Circle x: $x, y: $y, r: $r"
}
val p = Point()
val c = Circle()
println("Instantiated ", p)
println("Instantiated ", c)
val q = Point(5, 6)
println("Instantiated ", q)
val r = q.copy(y = 7) // change y coordinate
println(r, " changed y coordinate")
val d = Circle(5, 6, 7)
println("Instantiated ", d)
val e = d.copy(r = 8) // change radius
println(e, " changed radius")
}</syntaxhighlight>
=={{header|Seed7}}==
[http://seed7.sourceforge.net/manual/objects.htm Seed7 object orientation] works via interfaces.
The example below introduces the interface type ''GraphicObj''. To be usable an interface type needs also interface functions (which are defined with the keyword DYNAMIC). The interface function ''print'' is defined for ''GraphicObj''. The struct types ''Point'' and ''Circle'' implement the the interface ''GraphicObj'' (they are implementation types).
Note that ''Circle'' inherits ''x'' and ''y'' from ''Point''.
Functions which return a ''Point'' respectively ''Circle'' are used as constructors.
Note that a Seed7 constructor does not need to have the name of the type (a new Point could be created with a function called abc).
Seed7 defines copy constructor, assignment and destructor automatically.
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";
const type: GraphicObj is new interface;
Line 3,546 ⟶ 4,422:
graph := circ;
print(graph);
end func;</
{{out}}
Circle(3, 4, 5)
=={{header|Self}}==
We create four named objects, two of which we put in the traits namespace and two in a general prototype namespace. This would normally be done in the UI.
<
parent* = traits clonable.
printString = ('Point(', x asString, ':', y asString, ')').
Line 3,577 ⟶ 4,450:
center <- point copy.
r <- 0
|)</
=={{header|Sidef}}==
<
}
Line 3,594 ⟶ 4,467:
func pp(Circle obj) {
say "Circle at #{obj.x},#{obj.y} with radius #{obj.r}";
}</
Example:
<
var p = Point(1, 2); # create a point
pp(p); # => Point at 1,2
Line 3,608 ⟶ 4,481:
d.r = 7.5; # and change the radius to 7.5
pp(c); # => Circle at 4,5 with radius 6
pp(d); # => Circle at 4,5 with radius 7.5</
=={{header|SIMPOL}}==
Line 3,618 ⟶ 4,491:
The <code>embed</code> keyword in the type definition states that the type itself can be embedded in another type (any type can be placed as a reference in another type).
<
embed
integer x
Line 3,690 ⟶ 4,563:
result = p.print() + "{d}{a}" + c.print() + "{d}{a}"
end function result</
[[SIMPOL]] does not currently have access to stdin, stdout, and stderr,
Line 3,698 ⟶ 4,571:
=={{header|Smalltalk}}==
Like Python and Ruby, these objects do not need to be related in order to have polymorphic methods.
<
instanceVariableNames: 'x y'
classVariableNames: ''
Line 3,772 ⟶ 4,645:
!Circle methodsFor: 'polymorphism test'!
print
Transcript show: center; space; show: radius ! !</
''TODO: more idiomatic mechanism for presenting objects as strings.''
Line 3,778 ⟶ 4,651:
=={{header|Swift}}==
<
var x: Int
var y: Int
Line 3,823 ⟶ 4,696:
println(p.x) // 1
p.x = 8
println(p.x) // 8</
=={{header|Tcl}}==
Line 3,831 ⟶ 4,704:
We only do so here for convenience.
In addition, Tcl's arguments to commands, procedures and methods are all fully polymorphic by default.
<
oo::class create Point {
variable X Y
Line 3,883 ⟶ 4,756:
foreach o $objects {
$o print
}</
=={{header|Wollok}}==
<
class Point {
var x
Line 3,930 ⟶ 4,803:
c.print()
}
</syntaxhighlight>
=={{header|Wren}}==
Although Wren supports operator overloading, it is not possible to overload the assignment operator '='.
Objects in Wren are garbage collected when there are no longer any references to them. There is no support for destructors as such though, if you want to do some clean-up when an object is no longer needed, you can write a suitable method and then call it manually.
The following program uses the same examples as the Kotlin entry.
<syntaxhighlight lang="wren">class Point {
construct new(x, y) {
_x = x
_y = y
}
static new(x) { new(x, 0) }
static new() { new(0, 0) }
static fromPoint(p) { new(p.x, p.y) }
x { _x }
y { _y }
print() { System.print("Point at (%(_x), %(_y))") }
}
class Circle is Point {
construct new(x, y, r) {
super(x, y)
_r = r
}
static new(x, r) { new(x, 0, r) }
static new(x) { new(x, 0, 0) }
static new() { new(0, 0, 0) }
static fromCircle(c) { new(c.x, c.y, c.r) }
r { _r }
print() { System.print("Circle at center(%(x), %(y)), radius %(_r)") }
}
var points = [Point.new(), Point.new(1), Point.new(2, 3), Point.fromPoint(Point.new(3, 4))]
for (point in points) point.print()
var circles = [
Circle.new(), Circle.new(1), Circle.new(2, 3),
Circle.new(4, 5, 6), Circle.fromCircle(Circle.new(7, 8, 9))
]
for (circle in circles) circle.print()</syntaxhighlight>
{{out}}
<pre>
Point at (0, 0)
Point at (1, 0)
Point at (2, 3)
Point at (3, 4)
Circle at center(0, 0), radius 0
Circle at center(1, 0), radius 0
Circle at center(2, 0), radius 3
Circle at center(4, 5), radius 6
Circle at center(7, 8), radius 9
</pre>
=={{header|zkl}}==
Written for brevity
<
fcn init(xyOrPoint=0,_=0){
if(Point.isInstanceOf(xyOrPoint)) set(xyOrPoint);
Line 3,960 ⟶ 4,894:
c:=Circle(1,2,3);
c.println(); c.center.println();
c.copy().println();</
{{out}}
<pre>
|