Perl
Beginner
oop

Perlでメソッドをoverloadする方法

More than 5 years have passed since last update.

Perlではメソッドのオーバーロードが出来ない様ですね。まぁこんなだけ変数の型にゆるゆるだったら、出来るわけもないのかと思ったりもしますが、、、

代替策としてこんなのがあるみたい。
私としては、まとまってていいなーって感じです。

Triangle.pm
package Triangle;
use Carp qw(croak);

my $subSpace = sub {
        my($a,$b,$c) = @_;
        my $s = ($a + $b + $c) / 2;
        my $inRoot = $s * ($s - $a) * ($s - $b) * ($s - $c);
        if ($inRoot >= 0){
                return sqrt($inRoot);
        }else{
                croak "you cannot construct the triangle with the sides $a, $b, $c !";
        }
};
sub new{
        my ($class,$a,$b,$c) = @_;
        bless{a=>$a, b=>$b,c=>$c, s=>$subSpace->($a,$b,$c)};
#       my $self = {a=>$a, b=>$b, c=>$c};
#       bless $self, $class;
#       return $self;
}

sub space{
        my ($self) = shift;
        warn "You are about to calculate the space of ", ref($self), "!!!\n";
        return $self->{s};
}


sub getSides{
       my $self = shift;
       return ($self->{a}, $self->{b}, $self->{c});
}

sub setSides{
       my ($self, $a, $b, $c) = @_;
       $self->{a} = $a;
       $self->{b} = $b;
       $self->{c} = $c;
       $self->{s} = $subSpace->($a,$b,$c);
}

1;

このgetter setterの部分を、同じメソッド名にして、それぞれ引数の数に応じて呼ぶモジュールを変えます。

Triangle.pm~その2~
sub sides{
        my $self = shift; # invocant
        unless (@_) { # getter
                return ($self->{a}, $self->{b}, $self->{c}); # return properties
        } else { # setter
                my ($a, $b, $c) = @_;
                # get values from arguemnts and set properties
                $self->{a} = $a;
                $self->{b} = $b;
                $self->{c} = $c;
                $self->{s} = $subSpace->($a,$b,$c);
        }
}

モジュールはこんなもんで、あとはコレを呼ぶ側で、呼ぶメソッドをsetSides, getSidesからそれぞれsidesに統一したら完了です。

呼ぶ側のコードの例はこんな感じです。

triangleSpace.pl
#! /bin/perl -w

use Triangle;

my $tri = Triangle->new(3,4,5);
my $space = $tri->space;
print "sides are ", join(",",$tri->sides), ". \n";
print "Triangle is ",$tri," and its space is ",$space,"\n";

my ($a,$b,$c) = $tri->sides;
$tri->sides($a,$b,$c);
$space = $tri->space;
print "sides are ",join(", ",$tri->sides), ". \n";
print "Triangle is ",$tri," and its space is ",$space,"\n";

同じ結果になっていることを確認して頂けたでしょうか?

めんどいんだかなんだかわかりませんが、こんなやり方も出来るんですね~ 勉強になりました。