View Category
OOP

Define a class

Declare a class named Greeter that takes a string on creation and greets using this string if you call the "greet" method.
perl
{ package Greeter;
sub new {
my $self = {};
my $type = shift;
$self->{'whom'} = shift;
bless $self, $type;
}

sub greet {
my $self = shift;
print "Hello " . $self->{'whom'} . "!\n";
}
}

my $greeter = Greeter->new("world");
$greeter->greet();
{
package Greeter;

sub new {
my $class = shift;
my $whom = shift or die 'Need a name to greet';
bless \$whom, $class;
}

sub greet {
my $self = shift;
print "Hello $$self!\n";
}
}

my $greeter = Greeter->new("Bob");
$greeter->greet();
cpp
class Greeter
{
public:
Greeter(const std::string& whom);
void greet() const;

private:
std::string whom;
};

int main()
{
Greeter* gp = new Greeter("world");
gp->greet();
delete gp;
}

Greeter::Greeter(const std::string& whom) : whom(whom) {}

void Greeter::greet() const
{
std::cout << "Hello, " << whom << std::endl;
}
public ref class Greeter
{
public:
Greeter(String^ whom);
void greet();

private:
initonly String^ whom;
};

int main()
{
(gcnew Greeter(L"world"))->greet();
}

Greeter::Greeter(String^ whom) : whom(whom) {}

void Greeter::greet()
{
Console::WriteLine(L"Hello, {0}", whom);
}
csharp
using System;

class Greeter
{
private string name {get;set;}

public void Greet(){
Console.WriteLine("Hello, {0}",name);
}

public Greeter(string name){
this.name = name;
}
}

class Test
{
static void Main()
{
new Greeter("Dante").Greet();
}
}

Instantiate object with mutable state

Reimplement the Greeter class so that the 'whom' property or data member remains private but is mutable, and is provided with getter and setter methods. Invoke the setter to change the greetee, invoke 'greet', then use the getter in displaying the line, "I have just greeted {whom}.".

For example, if the greetee is changed to 'Tommy' using the setter, the 'greet' method would display:

Hello, Tommy!

The getter would then be used to display the line:

I have just greeted Tommy.
perl
package Greeter;
sub new {
my ($class, $whom) = @_;
bless {whom => $whom}, $class;
}
sub whom {
my ($self, $whom) = @_;
if ($whom) { $self->{whom} = $whom; }
else { return $self->{whom} }
}
sub greet {
my ($self) = @_;
my $whom = $self->{whom};
print "Hello, $whom!\n";
}
package main;

my $g = new Greeter ("world");
$g->greet;

$g->whom("Tommy");
$g->greet;
print "I have just greeted " . $g->whom . "\n";
cpp
#include <iostream>

using namespace std;

class Greeter {
string whom_;

public:
Greeter(const string &whom) : whom_(whom) {}

string get_whom() const {
return whom_;
}

void set_whom(const string &whom) {
whom_ = whom;
}

void greet() const {
cout << "Hello " << whom_ << "!" << endl;
}
};

int main()
{
Greeter greeter("world");
greeter.greet();
greeter.set_whom("Tommy");
greeter.greet();
cout << "I have just greeted " + greeter.get_whom() << "." << endl;
}
csharp
class Greeter
{
public string Name {get;set;}

public void Greet(){
Console.WriteLine("Hello, {0}",Name);
}

public Greeter(string name){
this.Name = name;
}

// Driver
public static void Main()
{
var g = new Greeter("Dante");

g.Name = "Tommy";
g.Greet();
Console.Write("I have just greated {0}", g.Name);
}
}

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.
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;
{
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;
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();
}
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();
}
}

Implement and use an Interface

Create a Serializable interface consisting of 'save' and 'restore' methods, each of which:

* Accept a stream or handle or descriptor argument for the source or destination
* Save to destination or restore from source the properties or data members of the implementing class (restrict yourself to the primitive types 'int' and 'string')

Next, create a Person class which has 'name' and 'age' properties or data members and implements this interface. Instantiate a Person object, save it to a serial stream, and instantiate a new Person object by restoring it from the serial stream.
perl
package Person;

use Moose;
use MooseX::Storage;
with Storage('format' => 'JSON', 'io' => 'File');

has 'name' => (is => 'rw', isa => 'Str');
has 'age' => (is => 'rw', isa => 'Int');

1;

Person->new( name => 'David B.', age => 28)->store('person.json');

my $p = Person->load('person.json');
{
package Serializable;
use Role::Basic;
use Storable qw'store_fd retrieve_fd';
use Scalar::Util 'blessed';
use IO::Handle;
use Carp;

sub save {
my $self = shift;
my $fd = shift or croak 'Needs target file handle';
$DB::single = (1);
store_fd($self, $fd);
}

sub restore {
my $class = shift;
my $fd = shift or croak 'Needs source file handle';
my $self = retrieve_fd( $fd );
bless $self, $class
}

}
{
package Person;
use Role::Basic 'with';
use Scalar::Util 'looks_like_number';
use Carp;

with 'Serializable';

sub new {
my $class = shift;
croak 'Invalid parameters' if (@_ % 2);
%parameters = @_;

do {
croak "Missing $_" unless defined $parameters{$_}
} for qw/name age/;
croak 'Invalid age' unless looks_like_number($parameters{age});
bless \%parameters, $class
}
sub name {
$self{name}
}
sub age {
$self{age}
}
}

use IO::Handle;
my $p1 = Person->new(age => 42, name => 'Milly Fogg');
open my $fh, '+>', 'person.store';
$p1->save( $fh );
seek $fh, 0, SEEK_SET;
my $p2 = Person->restore( $fh );
cpp
struct person
{
person(){}
person(const string &name, int age) : name_(name), age_(age) {}

string name_;
int age_;

template<typename Archive>
void serialize(Archive &ar, const unsigned int version) {
ar & name_ & age_;
}
};


int main()
{
const char *fn = "filename.txt";

person k("Ken", 38);
{
ofstream ofs(fn);
archive::text_oarchive oa(ofs);
oa << k;
}

person restored_person;
{
ifstream ifs(fn);
archive::text_iarchive ia(ifs);
ia >> restored_person;
}

cout << "Name : " << restored_person.name_ << endl
<< "Age : " << restored_person.age_ << endl;
}