Skip to content

Instantly share code, notes, and snippets.

@civitaspo
Last active December 23, 2015 01:09
Show Gist options
  • Save civitaspo/a45d8d284c3a238cf074 to your computer and use it in GitHub Desktop.
Save civitaspo/a45d8d284c3a238cf074 to your computer and use it in GitHub Desktop.
Study_OOP

継承による拡張性の追加

関数を直接継承するのではなく、クラス変数、そして関数のパラメータ となる関数を継承する・させることで、設計思想や、インターフェースを残しながら、 大きく拡張することが可能になる。

以下に自身のvalueを出力する3つの例を示す。

  • 直に継承してオーバーライドする場合(拡張性小)
  • 直接、to_valuesがオーバーライドされる
sub to_values {
    my $self = shift;
    return values %$self;
}
  • クラス変数をオーバーライドする場合(拡張性中)
  • クラスデータをオーバーライドすれば、拡張は出来るが、定められた形でしか出せず、いざとなれば、to_valuesがオーバーライドされる。
  • keys_for_valuesは直接関数で定義しても良い。
use parent qw(Class::Data::Inheritable);
__PACKAGE__->mk_classdata(keys_for_values => [qw/key1 key2 key3/]);

sub to_values {
    my $self = shift;
    return map { $self->{$_} } @{$self->keys_for_values()};
}
  • 関数をオーバーライドする場合(拡張性大)
  • a, b, cの変更や、funcname_for_valuesの中身を変更するだけで良く、重要なI/Fであるto_valuesが変更されることは殆どない
sub funcname_for_values {
    qw/a b c/;
}

sub a { my $self = shift; $self->{key1} }
sub b { my $self = shift; $self->{key2} }
sub c { my $self = shift; $self->{key3} }

sub to_values {
    my $self = shift;
    return map { $self->$_() } @{$self->funcname_for_hashref()};
}

継承ではなく、ジェネリックによる拡張 like C Sharp

  • 継承による拡張では、ポリモーフィズムを実現するために、オブジェクトのType分のクラスが必要になる。
  • 一方、ジェネリックによる拡張(C#では、宣言時に指定)を行うと、クラスがオブジェクトの数分必要になることはない。
  • Perlはオブジェクトの型を実行時まで認識せず扱えるため、宣言時のType指定で制限を行うようにすると良いと思う。
my $string = String->new('aiueo');
my $int = Int->new(348);
my $obj = Obj->new('Int'); # 継承による拡張では、ObjIntとObjStringを別々のクラスとして実装する必要がある。
$obj->add($int); # 成功
$obj->add($string); # ここでdieする

package Obj;
sub new {
    my ($class, $type) = @_;
    bless +{
        type => $type,
        array => +[],
    }, $class;
}

sub add {
    my ($self, @values) = @_;   
    die unless $_->isa($self->{type}) for @values;
    push @{$self->{array}}, $_ for @values;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment