View Problem
OOP

Implement Inheritance Heirarchy

Implement a Shape abstract class which will form the base of an inheritance hierarchy that models 2D geometric shapes. It will have:

* A non-mutable 'name' property or data member set by derived or descendant classes at construction time
* A 'area' method intended to be overridden by derived or descendant classes ( double precision floating point return value)
* A 'print' method (also for overriding) will display the shape's name, area, and all shape-specific values

Two derived or descendant classes will be created:
* Circle    -> Constructor requires a '
radius' argument, and a 'circumference' method to be implemented  
* Rectangle -> Constructor requires '
length' and 'breadth' arguments, and a 'perimeter' method to be implemented 

Instantiate an object of each class, and invoke each objects '
print' method to show relevant details.
DiskEdit
clojure
(defmulti area :Shape)
(defmulti print :Shape)

; Circle methods
(defn circle [r]
{:Shape :Circle
:name "Circle"
:radius r})

(defn circumference [c]
(* 2 Math/PI (:radius c)))

(defmethod area :Circle [c]
(* Math/PI (:radius c) (:radius c)))

(defmethod print :Circle [c]
(println (format "I am a %s with ->" (:name c)))
(println (format "Radius: %.2f" (:radius c)))
(println (format "Area: %.2f" (area c)))
(println (format "Circumference: %.2f" (circumference c))))

; Rectangle methods
(defn rectangle [l b]
{:Shape :Rectangle
:name "Rectangle"
:length l
:breadth b})

(defn perimeter [r]
(+ (* 2 (:length r)) (* 2 (:breadth r))))

(defmethod area :Rectangle [r]
(* (:length r) (:breadth r)))

(defmethod print :Rectangle [r]
(println (format "I am a %s with ->" (:name r)))
(println (format "Length, Width: %.2f, %.2f" (:length r) (:breadth r)))
(println (format "Area: %.2f" (area r)))
(println (format "Perimeter: %.2f" (perimeter r))))

; usage of the "classes"
(let [shapes (list (circle 4.2) (rectangle 2.7 3.1) (rectangle 6.2 2.6) (circle 17.3))]
(doseq [shape shapes]
(print shape)))
DiskEdit
cpp
#include <string>
#include <iostream>

using namespace std;

static const double PI = 3.141592;

class Shape {
protected:
string name_;
public:
Shape(const string& name) : name_(name) { }
virtual double area() const = 0;
virtual void print() const = 0;
};

class Circle : public Shape {
double radius_;
public:
Circle(double radius) : Shape("circle"), radius_(radius) { }
double area() const {
return PI * radius_ * radius_;
}
void print() const {
cout << "A " << name_ << " with radius " << radius_ << ", area "
<< area() << " and circumference " << circumference() << "."
<< endl;
}
double circumference() const {
return 2 * PI * radius_;
}
};

class Rectangle : public Shape {
double length_;
double breadth_;
public:
Rectangle(double length, double breadth) :
Shape("rectangle"), length_(length), breadth_(breadth) { }
double area() const {
return length_ * breadth_;
}
void print() const {
cout << "A " << name_ << " with length " << length_ << ", breadth "
<< breadth_ << ", area " << area() << " and perimeter "
<< perimeter() << "." << endl;
}
double perimeter() const {
return 2 * length_ + 2 * breadth_;
}
};

int main(int argc, char *argv[])
{
Circle circle(4);
circle.print();
Rectangle rectangle(2, 5.5);
rectangle.print();
}
DiskEdit
csharp
// While abstract classes do exist in C#, it is most common to use
// an interface in this type of situation.
// It is a common idiom to prefix interface names with an I
public interface IShape {
string Name { get; }
double Area { get; }
void Print();
}

public class Circle : IShape {

private double Radius { get; set; }
public Circle(double radius) {
Name = "Circle";
Radius = radius;
}

public string Name { get; private set; }
public double Area {
get {
return Math.PI * Radius * Radius;
}
}
public double Circumference {
get {
return Math.PI * (Radius + Radius);
}
}

public void Print() {
Console.WriteLine( " Name: {0}\n Area: {1}\n Circumference: {2}\n Radius: {3}",
this.Name,
this.Area,
this.Circumference,
this.Radius
);
}
}

public class Rectangle : IShape {

private double Length { get; set; }
private double Breadth { get; set; }
public Rectangle(double length, double breadth) {
Name = "Rectangle";
Length = length;
Breadth = breadth;
}

public string Name { get; private set; }
public double Area {
get {
return Length * Breadth;
}
}
public double Perimeter {
get {
return (Length * 2) + (Breadth * 2 );
}
}

public void Print() {
Console.WriteLine( " Name: {0}\n Area: {1}\n Perimeter: {2}\n Length: {3}\n Breadth: {4}",
this.Name,
this.Area,
this.Perimeter,
this.Length,
this.Breadth
);
}
}

// Driver
public class InheritanceHeirarchy {
public static void _Main() {
var c = new Circle(2.1);
c.Print();

Console.WriteLine();

var r = new Rectangle(2.2, 3.3);
r.Print();
}
}
DiskEdit
fantom
abstract class Shape
{
const Str name
new make(Str name) { this.name = name }
abstract Float area()
abstract Void print()
}

class Circle : Shape
{
private Float radius

new make(Float radius) : super("circle") { this.radius = radius }
Float circumference() { return 2 * Float.pi * radius }
override Float area() { return Float.pi * radius.pow(2.0f) }
override Void print()
{
echo("I am a $name with radius $radius, area $area
and circumference $circumference")
}
}

class Rectangle : Shape
{
private Float length
private Float breadth

new make(Float length, Float breadth) : super("rectangle")
{
this.length = length
this.breadth = breadth
}
Float perimeter() { return 2 * (length + breadth) }
override Float area() { return length * breadth }
override Void print()
{
echo("I am a $name with length $length, breadth $breadth,
area $area and perimeter $perimeter")
}
}


circle := Circle(4.0f)
circle.print
rectangle := Rectangle(2.0f, 5.5f)
rectangle.print
DiskEdit
fsharp
[<AbstractClass>]
type Shape(name:string) =
member this.Name = name
abstract Area : float
abstract Print : unit -> unit

type Circle(name, radius:float) =
inherit Shape(name)
member this.Radius = radius
member this.Circumference =
System.Math.PI * radius * 2.
override this.Area =
System.Math.PI * radius * radius
override this.Print() =
printfn "Circle: %s" this.Name
printfn "Area: %f" this.Area
printfn "Circumference: %f" this.Circumference
printfn "Radius: %f" this.Radius

type Rectangle(name, length:float, breadth:float) =
inherit Shape(name)
member this.Length = length
member this.Breadth = breadth
member this.Perimiter =
(length * 2.) + (breadth * 2.)
override this.Area =
length * breadth
override this.Print() =
printfn "Rectangle: %s" this.Name
printfn "Area: %f" this.Area
printfn "Perimiter: %f" this.Perimiter
printfn "Length: %f" this.Length
printfn "Breadth: %f" this.Breadth

let c = Circle("Foo", 2.1)
let r = Rectangle("Bar", 2.2, 3.3)

c.Print()
printfn ""
r.Print()
DiskEdit
groovy
abstract class Shape {
final name
Shape(name) { this.name = name }
abstract area()
abstract print()
}

class Circle extends Shape {
final radius
Circle(radius) {
super('circle')
this.radius = radius
}
def area() { Math.PI * radius * radius }
def circumference() { 2 * Math.PI * radius }
def print() {
println "I am a $name with ->"
printf 'Radius: %.2f\n', radius
printf 'Area: %.2f\n', area()
printf 'Circumference: %.2f\n', circumference()
}
}

class Rectangle extends Shape {
final length, breadth
def Rectangle(length, breadth) {
super("rectangle")
this.length = length
this.breadth = breadth
}
def area() { length * breadth }
def perimeter() { 2 * length + 2 * breadth }
def print() {
println "I am a $name with ->"
printf 'Length, Width: %.2f, %.2f\n', length, breadth
printf 'Area: %.2f\n', area()
printf 'Perimeter: %.2f\n', perimeter()
}
}

shapes = [new Circle(4.2), new Rectangle(2.7, 3.1), new Rectangle(6.2, 2.6), new Circle(17.3)]
shapes.each { shape -> shape.print() }
DiskEdit
haskell
data Circle = C { namec :: String, radius :: Float }
data Rectangle = R { namer :: String, len :: Float, breadth :: Float }

circumference (C _ r) = 2 * pi * r
perimeter (R _ l b) = 2 * (l + b)

class Shape a where
area :: a -> Float
name :: a -> String
println :: a -> IO ()

instance Shape Circle where
area (C _ r) = pi * r * r
println c = print $ namec c ++ " : area = " ++
show (area c) ++ ", radius = " ++
show (radius c)
name (C n _) = n

instance Shape Rectangle where
area (R _ l b) = l * b
println r = print $ namer r ++ " : area = " ++
show (area r) ++ ", length = " ++
show (len r) ++ ", breadth = " ++
show (breadth r)
name (R n _ _) = n

main = do
let c = C { namec = "Circle", radius = 2.34 }
r = R { namer = "Rectangle", len = 3.4, breadth = 2.456 }
println c
println r
ExpandDiskEdit
java 1.5 or above
/*
* Will work with version 1.4 if you remove the @Override annotation
* and declare floating point numbers using the primitive "double"
*/
abstract class Shape {
protected final String name;
public Shape(String name) {
this.name = name;
}
public abstract Double area();
public abstract void print();
}
class Circle extends Shape {
private Double radius;
public Circle(Double radius) {
super("circle");
this.radius = radius;
}
@Override
public Double area() {
return Math.PI * Math.pow(radius, 2);
}
@Override
public void print() {
System.out.println("A " + name + " with radius " + radius
+ ", area " + area() + " and circumference "
+ circumference() + ".");
}
public Double circumference() {
return 2 * Math.PI * radius;
}
}
class Rectangle extends Shape {
private Double length, breadth;
public Rectangle(Double length, Double breadth) {
super("Rectangle");
this.length = length;
this.breadth = breadth;
}
@Override
public Double area() {
return length * breadth;
}
public Double perimeter() {
return 2 * length + 2 * breadth;
}
@Override
public void print() {
System.out.println("A " + name + " with length " + length
+ ", breadth " + breadth + ", area " + area()
+ " and perimeter " + perimeter() + ".");
}
}
Circle circle = new Circle(4d);
circle.print();
Rectangle rectangle = new Rectangle(2d, 5.5);
rectangle.print();
DiskEdit
ocaml
class virtual shape =
object(self)
method name = "shape"
method virtual area : float
method print = Printf.sprintf "%s, area %f" self#name self#area
end ;;

let pi = 4. *. atan 1.

class circle radius =
object(self)
inherit shape as super
method name = "circle"
method area = radius *. radius *. pi
method circumference = radius *. 2. *. pi
method print = Printf.sprintf "%s, circumference %f" super#print self#circumference
end

class rectangle length breadth =
object(self)
inherit shape as super
method name = "rectangle"
method area = length *. breadth
method perimeter = 2. *. ( length +. breadth)
method print = Printf.sprintf "%s, perimeter %f" super#print self#perimeter
end

let c = new circle 5. in
let r = new rectangle 7. 3. in
print_endline c#print;
print_endline r#print
DiskEdit
perl
package Shapes;

use MooseX::Declare;

class Shape {
use MooseX::ABC;
requires qw/area print/;
has 'name' => (is => 'ro', isa => 'Str', default => '', required => 0, init_arg => undef );

}

class Circle extends Shape {
use constant PI => 4 * atan2(1, 1);

has '+name' => ( default => 'circle' );
has 'radius' => (is => 'ro', isa => 'Num', required => 1, init_arg => 'r' );

sub area { PI * ( $_[0]->radius ** 2 ) }
sub circumference { 2 * PI * ( $_[0]->radius ** 2 ) }

sub print {
my $self = shift;

printf <<"END_OF_BLOCK", map { $self->$_ } qw/name radius area circumference/;
I am a '%s' with
Radius: %.2f
Area: %.2f
Circumference: %.2f
END_OF_BLOCK

}

}

class Rectangle extends Shape {

has '+name' => ( default => 'rectangle' );
has 'length' => (is => 'ro', isa => 'Num', required => 1, init_arg => 'l' );
has 'breadth' => (is => 'ro', isa => 'Num', required => 1, init_arg => 'b' );

sub area { $_[0]->length * $_[0]->breadth }
sub perimeter { 2 * ( $_[0]->length + $_[0]->breadth ) }

sub print {
my $self = shift;

printf <<"END_OF_BLOCK", map { $self->$_ } qw/name length breadth area perimeter/;
I am a '%s' with
Length, Width: %.2f, %.2f
Area: %.2f
Perimeter: %.2f
END_OF_BLOCK

}

}

1;

package main;

my @shapes = ( Circle->new( r => 4.2 ), Rectangle->new(l => 2.7, b => 3.1),
Rectangle->new(l => 6.2, b => 2.6), Circle->new( r => 17.3) );
$_->print for @shapes;
DiskEdit
perl
{
package Shapes;

sub new {
my $class = shift;
die 'Invalid parameters' if (@_ % 2);
my %parameters = @_;
die 'Missing name' unless defined $parameters{name};
bless \%parameters, $class
}

sub area {
die
'area() method must be implemented by ',__PACKAGE__.' subclasses';
}
sub print {
my $self = shift;
printf "Name: \t%s\n", $self->{name};
printf "Area: \t%.2f\n", $self->area();
}
}

{
package Circle;
use parent -norequire, 'Shapes';
use Scalar::Util qw/looks_like_number/;
use Math::Trig;

sub new {
my $class = shift;
my $self = $class->SUPER::new(name => 'Circle', @_);
die 'Missing radius' unless defined($self->{radius});
die 'Invalid radius (not a number)'
unless looks_like_number($self->{radius});
$self
}
sub area {
my $self = shift;
pi * ($self->{radius} ** 2)
}
sub circumference {
my $self = shift;
2 * pi * $self->{radius};
}
sub print {
my $self = shift;
$self->SUPER::print;
printf "Circumference: \t%.2f\n", $self->circumference;
}

}

{
package Rectangle;
use parent -norequire, 'Shapes';
use Scalar::Util qw/looks_like_number/;

sub new {
my $class = shift;
my $self = $class->SUPER::new(name => 'Rectangle', @_);
do {
die "Missing $_" unless defined($self->{$_});
die "Invalid $_" unless looks_like_number($self->{$_});
} for qw/length breadth/;
$self;
}
sub area {
my $self = shift;
$self->{length} * $self->{breadth}
}
sub print {
my $self = shift;
$self->SUPER::print();
do {
printf ucfirst($_).": \t%.2f\n", $self->{$_}
} for qw/length breadth/;
}
}


package main;

my @shapes = ( Circle->new( radius => 4.2 ),
Rectangle->new(length => 2.7, breadth => 3.1),
Rectangle->new(length => 6.2, breadth => 2.6),
Circle->new( radius => 17.3) );
$_->print for @shapes;
ExpandDiskEdit
php 5 (tested in 5.3)
<?php
abstract class Shape
{
protected $name;
abstract public function area ();
abstract public function _print ();
public function __construct ($name)
{
$this->name = $name;
}
}

class Circle extends Shape
{
protected $radius;
public function __construct ($radius)
{
parent::__construct('Circle');
$this->radius = $radius;
}
public function area ()
{
return pi() * $this->radius * $this->radius;
}
public function circumference ()
{
return 2 * pi() * $this->radius;
}
public function _print ()
{
print("I am a {$this->name} with ->\n");
print(" Radius: {$this->radius}\n");
print(" Area: {$this->area()}\n");
print(" Circumference {$this->circumference()}\n");
}
}

class Rectangle extends Shape
{
protected $length;
protected $breadth;
public function __construct ($length, $breadth)
{
parent::__construct('Rectangle');
$this->length = $length;
$this->breadth = $breadth;
}
public function area ()
{
return $this->length * $this->breadth;
}
public function perimeter ()
{
return (2 * $this->length) + (2 * $this->breadth);
}
public function _print ()
{
print("I am a {$this->name} with ->\n");
print(" Length, Width: {$this->length}, {$this->breadth}\n");
print(" Area: {$this->area()}\n");
print(" Perimeter: {$this->perimeter()}\n");
}
}

$shapes = array(new Circle(4.2) , new Rectangle(2.7, 3.1) , new Rectangle(6.2, 2.6) , new Circle(17.3));

foreach ($shapes as $shape) {
$shape->_print();
}
DiskEdit
python 2.5 or 2.6, not 3
#Start with the import statements.
import math # necessary to get the value of pi

class Shape(object):
"""Shape Class"""
def __init__(self):
"""Constructor method"""
pass #Do nothing here
def area(self):
"""The area method"""
pass #Do nothing here
def print_(self):
"""
The print method. Note the trailing underscore - this is because
there is a reserved statement called 'print' in python 2.x. The
trailing underscore is the accepted method of re-using names without
rebinding them
"""
print 'The name is: %s' % self.name #Print the only property we currently have

def _getName(self):
"""The getter method for the 'name' property.
Note that getter methods are generally discouraged in python"""
return self._name

_name = None # The leading underscore gives a weak non-public value
# to a variable. Two leading underscores will mangle its
# name at runtime, to make it more difficult to access.
# Note there is no real 'private' variable type in python.
name = property(_getName, doc='The name of this object')
# property statements work like: property(fget=None, fset=None, fdel=None, doc=None)

class Circle(Shape):
"""Circle Class - a sub class of shape"""
def __init__(self, radius, name='Circle'):
"""Constructor method again"""
Shape.__init__(self) # init the super class
self.radius = radius # Store the radius
self._setCircumference()# Function call
self._name = name

def _setCircumference(self):
self.circumference = 2*math.pi*self.radius

def area(self):
'''Return the area of this circle'''
tmpAera = math.pi * self.radius**2
return tmpAera
def print_(self):
'''The print method'''
super(Circle, self).print_() # This calls the print_ method in
# the super classes of Circle, in
# this case Shape
print 'The radius is: %f' % self.radius
print 'The circumference is %f' % self.circumference
print 'The area is: %f' % self.area()

class Rectangle(Shape):
"""The Rectangle Class"""
def __init__(self, length, breadth, name='Rectangle'):
Shape.__init__(self)
self._name = name
self.length = length
self.breadth = breadth
self.perimeter()
def area(self):
return self.breadth*self.length
def perimeter(self):
self._perimeter = self.breadth*2+self.length*2
return self._perimeter # You have a method return a value and still
# safely call it without handling the return
# value. This would be collected by garbage
# collection.
def print_(self):
super(Rectangle, self).print_()
print 'The length is %f and the breadth is %f' %(self.length, self.breadth)
print 'The perimeter is: %f' %self._perimeter
print 'The area is: %f' % self.area()

if __name__ == '__main__':
rectangle = Rectangle(5,3)
circle = Circle(5, name='Round and Round')
rectangle.print_()
circle.print_()
DiskEdit
ruby
class Shape
def initialize(name="") @name = name end
end

class Circle < Shape
def initialize(radius) super("circle") ; @radius = radius end

def area() 3.14159 * @radius * @radius end
def circumference() 2 * 3.14159 * @radius end

def print()
puts "I am a #{@name} with ->"
puts "Radius: %.2f" % @radius
puts "Area: %.2f" % self.area()
puts "Circumference: %.2f\n" % self.circumference()
end

end

class Rectangle < Shape
def initialize(length, breadth) super("rectangle") ; @length = length ; @breadth = breadth end

def area() @length * @breadth end
def perimeter() 2 * @length + 2 * @breadth end

def print()
puts "I am a #{@name} with ->"
printf("Length, Width: %.2f, %.2f\n", @length, @breadth)
puts "Area: %.2f" % self.area()
puts "Perimeter: %.2f\n" % self.perimeter()
end
end

# ------

shapes = [Circle.new(4.2), Rectangle.new(2.7, 3.1), Rectangle.new(6.2, 2.6), Circle.new(17.3)]
shapes.each {|shape| shape.print}

ExpandDiskEdit
scala
abstract class Shape (val name: String) {
def area : Double
def print()
}

class Circle (val radius: Double) extends Shape("Circle") {
def area = Math.Pi * radius * radius
def circumference = 2 * Math.Pi * radius
def print() {
println("I'm a " + name + " with")
printf(" * radius = %.2f\n", radius)
printf(" * area = %.2f\n", area)
printf(" * circumference = %.2f\n\n", circumference)
}
}

class Rectangle (val length: Double, val breadth: Double) extends Shape("Rectangle") {
def area = length * breadth
def perimeter = 2 * (length + breadth)
def print() {
println("I'm a " + name + " with")
printf(" * length = %.2f\n", length)
printf(" * breadth = %.2f\n", breadth)
printf(" * area = %.2f\n", area)
printf(" * perimeter = %.2f\n\n", perimeter)
}
}

val shapes = List(new Circle(5.4), new Rectangle(7.8, 6.5))
shapes foreach (_.print)

Submit a new solution for clojure, cpp, csharp, fantom ...