Polymorphism: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 719: Line 719:
}
}


==[[C sharp|C#]]==
==[[C sharp|C# TODO]]==
[[Category:C sharp]]
[[Category:C sharp]]



==[[D]]==
==[[D]]==

Revision as of 02:48, 24 February 2007

Task
Polymorphism
You are encouraged to solve this task according to the task description, using any language you may know.

Create two classes Point(x,y) and Circle(x,y,r) with a polymorphic function print, accessors for (x,y,r), copy constructor, assignment and destructor and every possible default constructors

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.

package Shapes is
   type Point is tagged private;
   procedure Print(Item : in Point);
   function Setx(Item : in Point; Val : Integer) return Point;
   function Sety(Item : in Point; Val : Integer) return Point;
   function Getx(Item : in Point) return Integer;
   function Gety(Item : in Point) return Integer;
   function Create return Point;
   function Create(X : Integer) return Point;
   function Create(X, Y : Integer) return Point;
  
private
   type Point is tagged record
      X : Integer := 0;
      Y : Integer := 0;
   end record;
end Shapes;
with Ada.Text_Io; use Ada.Text_Io;

package body Shapes is

   -----------
   -- Print --
   -----------

   procedure Print (Item : in Point) is
   begin
      Put_line("Point");
   end Print;

   ----------
   -- Setx --
   ----------

   function Setx (Item : in Point; Val : Integer) return Point is
   begin
      return (Val, Item.Y);
   end Setx;

   ----------
   -- Sety --
   ----------

   function Sety (Item : in Point; Val : Integer) return Point is
   begin
      return (Item.X, Val);
   end Sety;

   ----------
   -- Getx --
   ----------

   function Getx (Item : in Point) return Integer is
   begin
      return Item.X;
   end Getx;

   ----------
   -- Gety --
   ----------

   function Gety (Item : in Point) return Integer is
   begin
      return Item.Y;
   end Gety;

   ------------
   -- Create --
   ------------

   function Create return Point is
   begin
      return (0, 0);
   end Create;

   ------------
   -- Create --
   ------------

   function Create (X : Integer) return Point is
   begin
      return (X, 0);
   end Create;

   ------------
   -- Create --
   ------------

   function Create (X, Y : Integer) return Point is
   begin
      return (X, Y);
   end Create;

end Shapes;

The following is the child package defining the Circle type.

package Shapes.Circles is
   type Circle is new Point with private;
   procedure Print(Item : Circle);
   function Setx(Item : Circle; Val : Integer) return Circle;
   function Sety(Item : Circle; Val : Integer) return Circle;
   function Setr(Item : Circle; Val : Integer) return Circle;
   function Getr(Item : Circle) return Integer;
   function Create(P : Point) return Circle;
   function Create(P : Point; R : Integer) return Circle;
   function Create(X : Integer) return Circle;
   function Create(X : Integer; Y : Integer) return Circle;
   function Create(X : Integer; Y : Integer; R : Integer) return Circle;
   function Create return Circle;
private
   type Circle is new Point with record
      R : Integer := 0;
   end record;
end Shapes.Circles;
with Ada.Text_Io; use Ada.Text_IO;

package body Shapes.Circles is

   -----------
   -- Print --
   -----------

   procedure Print (Item : Circle) is
   begin
      Put_line("Circle");
   end Print;

   ----------
   -- Setx --
   ----------

   function Setx (Item : Circle; Val : Integer) return Circle is
   begin
      return (Val, Item.Y, Item.R);
   end Setx;

   ----------
   -- Sety --
   ----------

   function Sety (Item : Circle; Val : Integer) return Circle is
      Temp : Circle := Item;
   begin
      Temp.Y := Val;
      return Temp;
   end Sety;

   ----------
   -- Setr --
   ----------

   function Setr (Item : Circle; Val : Integer) return Circle is
   begin
      return (Item.X, Item.Y, Val);
   end Setr;

   ----------
   -- Getr --
   ----------

   function Getr (Item : Circle) return Integer is
   begin
      return Item.R;
   end Getr;

   ------------
   -- Create --
   ------------

   function Create (P : Point) return Circle is
   begin
      return (P.X, P.Y, 0);
   end Create;

   ------------
   -- Create --
   ------------

   function Create (P : Point; R : Integer) return Circle is
   begin
      return (P.X, P.Y, R);
   end Create;

   ------------
   -- Create --
   ------------

   function Create (X : Integer) return Circle is
   begin
      return (X, 0, 0);
   end Create;

   ------------
   -- Create --
   ------------

   function Create (X : Integer; Y : Integer) return Circle is
   begin
      return (X, Y, 0);
   end Create;

   ------------
   -- Create --
   ------------

   function Create (X : Integer; Y : Integer; R : Integer) return Circle is
   begin
      return (X, Y, R);
   end Create;

   ------------
   -- Create --
   ------------

   function Create return Circle is
   begin
      return (0, 0, 0);
   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.

with Shapes.Circles; use Shapes.Circles;
use Shapes;

procedure Shapes_Main is
   P : Point;
   C : Circle;
begin
   Print(P);
   Print(C);
end Shapes_Main;


BASIC

Interpeter: QuickBasic 4.5, PB 7.1

DECLARE SUB PointInit0 (pthis AS Point)
DECLARE SUB PointInit1 (pthis AS Point, x0 AS INTEGER)
DECLARE SUB PointInit2 (pthis AS Point, x0 AS INTEGER, y0 AS INTEGER)
DECLARE FUNCTION PointGetX%(pthis AS Point)
DECLARE FUNCTION PointGetY%(pthis AS Point)
DECLARE SUB PointSetX (pthis AS Point, x0 AS INTEGER)
DECLARE SUB PointSetY (pthis AS Point, y0 AS INTEGER)
DECLARE SUB PointPrint (pthis AS Point)
DECLARE SUB CircleInit0 (pthis AS Circle)
DECLARE SUB CircleInit1 (pthis AS Circle, x0 AS INTEGER)
DECLARE SUB CircleInit2 (pthis AS Circle, x0 AS INTEGER, y0 AS INTEGER)
DECLARE SUB CircleInit3 (pthis AS Circle, x0 AS INTEGER, y0 AS INTEGER, r0 AS INTEGER)
DECLARE SUB CircleInitP0 (pthis AS Circle, p as Point)
DECLARE SUB CircleInitP0 (pthis AS Circle, p as Point, r0 AS INTEGER)
DECLARE FUNCTION CircleGetX%(pthis AS Circle)
DECLARE FUNCTION CircleGetY%(pthis AS Circle)
DECLARE FUNCTION CircleGetR%(pthis AS Circle)
DECLARE SUB CircleSetX (pthis AS Circle, x0 AS INTEGER)
DECLARE SUB CircleSetY (pthis AS Circle, y0 AS INTEGER)
DECLARE SUB CircleSetR (pthis AS Circle, r0 AS INTEGER)
DECLARE SUB CirclePrint (pthis AS Circle)
DECLARE SUB PolyPrint (pthis AS ANY, type%)
TYPE Point
  x AS INTEGER
  y AS INTEGER
END TYPE
TYPE Circle
  p AS Point
  r AS INTEGER
END TYPE
DIM SHARED POINT%, CIRCLE%
POINT% = 0
CIRCLE% = 1
DIM p AS Point
DIM c AS Circle
PointInit p
CircleInit c
REM No virtual function call possible
PointPrint p
CirclePrint c
REM Faked virtual function
PolyPrint p, POINT%
PolyPrint c, CIRCLE%
END
 SUB PolyPrint (pthis AS ANY, type%)
 IF (type% = CIRCLE%) THEN
   CirclePrint pthis
 ELSE
   PointPrint pthis
 END IF
 END SUB
 SUB PointInit0 (pthis AS Point)
   pthis.x = 0
   pthis.y = 0
 END SUB
 SUB PointInit1 (pthis AS Point, x0 AS INTEGER)
   pthis.x = x0
   pthis.y = 0
 END SUB
 SUB PointInit2 (pthis AS Point, x0 AS INTEGER, y0 AS INTEGER)
   pthis.x = x0
   pthis.y = y0
 END SUB
 FUNCTION PointGetX% (pthis AS Point)
   PointGetX% = pthis.x
 END SUB
 FUNCTION PointGetY% (pthis AS Point)
   PointGetY% = pthis.y
 END SUB
 SUB PointSetX (pthis AS Point, x0 AS INTEGER)
   pthis.x = x0
 END SUB
 SUB PointSetY (pthis AS Point, y0 AS INTEGER)
   pthis.y = y0
 END SUB
 SUB PointPrint (pthis AS Point)
   PRINT "Point"
 END SUB
 SUB CircleInit0 (pthis AS Circle)
   pthis.x = 0
   pthis.y = 0
   pthis.r = 0
 END SUB
 SUB CircleInit1 (pthis AS Circle, x0 AS INTEGER)
   pthis.x = x0
   pthis.y = y0
   pthis.r = 0
 END SUB
 SUB CircleInit2 (pthis AS Circle, x0 AS INTEGER, y0 AS INTEGER)
   pthis.x = x0
   pthis.y = y0
   pthis.r = 0
 END SUB
 SUB CircleInit3 (pthis AS Circle, x0 AS INTEGER, y0 AS INTEGER, r0 AS INTEGER)
   pthis.x = x0
   pthis.y = y0
   pthis.r = r0
 END SUB
 SUB CircleInitP0 (pthis AS Circle, p as Point)
   pthis.x = p.x
   pthis.y = p.y
   pthis.r = 0
 END SUB
 SUB CircleInitP0 (pthis AS Circle, p as Point, r0 AS INTEGER)
   pthis.x = p.x
   pthis.y = p.y
   pthis.r = r0
 END SUB
 FUNCTION CircleGetX% (pthis AS Circle)
   CircleGetX% = pthis.x
 END SUB
 FUNCTION CircleGetY% (pthis AS Circle)
   CircleGetY% = pthis.y
 END SUB
 FUNCTION CircleGetR% (pthis AS Circle)
   CircleGetR% = pthis.r
 END SUB
 SUB CircleSetX (pthis AS Circle, x0 AS INTEGER)
   pthis.x = x0
 END SUB
 SUB CircleSetY (pthis AS Circle, y0 AS INTEGER)
   pthis.y = y0
 END SUB
 SUB CircleSetR (pthis AS Circle, r0 AS INTEGER)
   pthis.r = r0
 END SUB
 SUB CirclePrint (pthis AS Circle)
   PRINT "Circle"
 END SUB

C

Compiler: GCC, MSVC, BCC, Watcom

Libraries: Standard

 /* After reading this you may understand */ 
 /* why Bjarne Stroustrup's invented C++  */
 #if defined( _WIN32 ) || defined( MSC_VER )
 #define FN_PTR(x) (& x)
 #else
 #define FN_PTR(x) (x)
 #endif
 typedef struct Point
 {
   int x;
   int y;
   void (*dtor)();   /* virtual */
   void (*print)();  /* virtual */
 } Point;
 Point* Point_new0()
 {
   Point* pthis = (Point*) malloc( sizeof( Point ) );
   memset(pthis, 0, sizeof( Point ) );
   pthis->dtor  = FN_PTR(Point_dtor);
   pthis->print = FN_PTR(Point_print);
 }
 Point* Point_new1(int x0)
 {
   Point* pthis = (Point*) malloc( sizeof( Point ) );
   pthis->x = x0;
   pthis->y = 0;
   pthis->dtor  = FN_PTR(Point_dtor);
   pthis->print = FN_PTR(Point_print);
 }
 Point* Point_new2(int x0, int y0)
 {
   Point* pthis = (Point*) malloc( sizeof( Point ) );
   pthis->x = x0;
   pthis->y = y0;
   pthis->dtor  = FN_PTR(Point_dtor);
   pthis->print = FN_PTR(Point_print);
 }
 void Point_delete(Point** pthis)
 {
   if(pthis && *pthis)
   {
     (*pthis)->dtor();
     free(*pthis); *pthis = NULL;
   }
 }
 Point* Point_copy(Point* p)
 {
   Point* pthis = (Point*) malloc( sizeof( Point ) );
   memcpy(pthis, p, sizeof( Point ) );
   pthis->dtor  = FN_PTR(Point_dtor);
   pthis->print = FN_PTR(Point_print);
   return pthis;
 }
 int Point_getX(Point* pthis) { return pthis->x; }
 int Point_getY(Point* pthis) { return pthis->y; }
 int Point_setX(Point* pthis, int x0) { pthis->x = x0; }
 int Point_setY(Point* pthis, int y0) { pthis->y = y0; }
 void Point_print() { printf("Point\n"); }
 void Point_dtor() {}
 // Trick: This way Circle.x, Circle.y, Circle.r are available
 typedef union Circle
 {
   Point point;
   struct _Circle
   {
     Point point;
     int r;
   };
 } Circle;


 Circle* Circle_new0()
 {
   Circle* pthis = (Circle*) malloc( sizeof( Circle ) );
   memset(pthis, 0, sizeof( Circle ) );
   pthis->dtor  = FN_PTR(Circle_dtor);
   pthis->print = FN_PTR(Circle_print);
 }
 Circle* Circle_new1(int x0)
 {
   Circle* pthis = (Circle*) malloc( sizeof( Circle ) );
   pthis->x = x0;
   pthis->y = 0;
   pthis->r = 0;
   pthis->dtor  = FN_PTR(Circle_dtor);
   pthis->print = FN_PTR(Circle_print);
 }
 Circle* Circle_new2(int x0, int y0)
 {
   Circle* pthis = (Circle*) malloc( sizeof( Circle ) );
   pthis->x = x0;
   pthis->y = y0;
   pthis->r = 0;
   pthis->dtor  = FN_PTR(Circle_dtor);
   pthis->print = FN_PTR(Circle_print);
 }
 Circle* Circle_new3(int x0, int y0, int r0)
 {
   Circle* pthis = (Circle*) malloc( sizeof( Circle ) );
   pthis->x = x0;
   pthis->y = y0;
   pthis->r = r0;
   pthis->dtor  = FN_PTR(Circle_dtor);
   pthis->print = FN_PTR(Circle_print);
 }
 Circle* Circle_newP0(Point* p)
 {
   Circle* pthis = (Circle*) malloc( sizeof( Circle ) );
   pthis->x = p->x;
   pthis->y = p->y;
   pthis->r = 0;
   pthis->dtor  = FN_PTR(Circle_dtor);
   pthis->print = FN_PTR(Circle_print);
 }
 Circle* Circle_newP1(Point* p, int r0)
 {
   Circle* pthis = (Circle*) malloc( sizeof( Circle ) );
   pthis->x = p->x;
   pthis->y = p->y;
   pthis->r = r0;
   pthis->dtor  = FN_PTR(Circle_dtor);
   pthis->print = FN_PTR(Circle_print);
 }
 void Circle_delete(Circle** pthis)
 {
   if(pthis && *pthis)
   {
     (*pthis)->dtor();
     free(*pthis); *pthis = NULL;
   }
 }
 Circle* Circle_copy(Circle* c)
 {
   Circle* pthis = (Circle*) malloc( sizeof( Circle ) );
   memcpy(pthis, c, sizeof( Circle ) );
   pthis->dtor  = FN_PTR(Circle_dtor);
   pthis->print = FN_PTR(Circle_print);
   return pthis;
 }
 int Circle_getX(Circle* pthis) { return pthis->x; }
 int Circle_getY(Circle* pthis) { return pthis->y; }
 int Circle_getR(Circle* pthis) { return pthis->r; }
 int Circle_setX(Circle* pthis, int x0) { pthis->x = x0; }
 int Circle_setY(Circle* pthis, int y0) { pthis->y = y0; }
 int Circle_setR(Circle* pthis, int r0) { pthis->r = r0; }
 void Circle_print() { printf("Circle\n"); }
 void Circle_dtor() {}
 int main()
 {
    Point* p = Point_new0();
    Point* c = (Point*)Circle_new0();
    p->print();
    c->print();     
    return 0;
 }

C++

Compiler: GCC, Visual C++, BCC, Watcom

 class Point
 {
   protected:
     int x, y;
   public:
     Point(int x0 = 0, int y0 = 0) : x(x0), y(y0) {}
     Point(const Point& p) : x(p.x), y(p.y) {}
     virtual ~Point() {}
     const Point& operator=(const Point& p)
     {
       if(this != &p)
       {
         x = p.x;
         y = p.y;
       }
       return *this;
     }
     int getX() { return x; }
     int getY() { return y; }
     int setX(int x0) { x = x0; }
     int setY(int y0) { y = y0; }
     virtual void print() { printf("Point\n"); }
 };
 class Circle : public Point
 {
   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& c)
     {
       if(this != &c)
       {
         x = c.x;
         y = c.y;
         r = c.r;
       }
       return *this;
     }
     int getR() { return r; }
     int setR(int r0) { r = r0; }
     virtual void print() { printf("Circle\n"); }
 };
 int main()
 {
   Point* p = new Point();
   Point* c = new Circle();
   p->print();
   c->print();     
   return 0;
 }

Pattern: Curiously Recurring Template Pattern

Compiler: GCC, Visual C++, BCC, Watcom

 // CRTP: Curiously Recurring Template Pattern
 template <typename Derived>
 class PointShape
 {
 protected:
   int x, y;
 public:
   PointShape(int x0, int y0) : x(x0), y(y0) { }
   ~PointShape() { }
   int getX() { return x; }
   int getY() { return y; }
   int setX(int x0) { x = x0; }
   int setY(int y0) { y = y0; }
   // compile-time virtual function
   void print() { reinterpret_cast<const Derived*>(this)->printType(); }
 };
 class Point : public PointShape<Point>
 {
 public:
   Point(int x0 = 0, int y0 = 0) : PointShape(x0, y0) { }
   Point(const Point& p) : PointShape(p.x, p.y) { }
   ~Point() {}
   const Point& operator=(const Point& p)
   {
     if(this != &p)
     {
       x = p.x;
       y = p.y;
     }
     return *this;
   }
   void printType() { printf("Point\n"); }
 };
 class Circle : public PointShape<Circle>
 {
 private:
   int r;
 public:
   Circle(int x0 = 0, int y0 = 0, int r0 = 0) : PointShape(x0, y0), r(r0) { }
   Circle(Point p, int r0 = 0) : PointShape(p.x, p.y), r(r0) { }
   ~Circle() {}
   const Circle& operator=(const Circle& c)
   {
     if(this != &c)
     {
       x = c.x;
       y = c.y;
       r = c.r;
     }
     return *this;
   }
   int getR() { return r; }
   int setR(int r0) { r = r0; }
   void printType() { printf("Circle\n"); }
 };
 int main()
 {
   Point* p = new Point();
   Point* c = new Circle();
   p->print();
   c->print();
   return 0;
 }

C# TODO

D

Compiler: DMD,GDC

Forth

Fortran

Java

class Point
{
  protected int x, y;
  public Point() { this(0); }
  public Point(int x0) { this(x0,0); }
  public Point(int x0, int y0) { x = x0; y = y0; }
  public int getX() { return x; }
  public int getY() { return y; }
  public int setX(int x0) { x = x0; }
  public int setY(int y0) { y = y0; }
  public void print() { System.out.println("Point"); }
}
public class Circle extends Point
{
  private int r;
  public Circle(Point p) { this(p,0); }
  public Circle(Point p, int r0) { super(p); r = r0; }
  public Circle() { this(0); }
  public Circle(int x0) { this(x0,0); }
  public Circle(int x0, int y0) { this(x0,y0,0); }
  public Circle(int x0, int y0, int r0) { super(x0,y0); r = r0; }
  public int getR() { return r; }
  public int setR(int r0) { r = r0; }
  public void print() { System.out.println("Circle"); }
  public static void main(String args[])
  {
    Point p = new Point();
    Point c = new Circle();
    p.print();
    c.print();     
  }
}

JavaScript


Perl

Interpeter: Perl


PHP