perlとrubyのオブジェクト指向の比較

perl

Parent.pm
package Parent;

use strict;
use warnings;

use base qw/Class::Accessor::Fast Class::Data::Inheritable/;
use Data::Dumper;

__PACKAGE__->mk_accessors(qw/name/);
__PACKAGE__->mk_ro_accessors(qw/for_read/);
__PACKAGE__->mk_wo_accessors(qw/for_write/);
__PACKAGE__->mk_classdata('classvar');
__PACKAGE__->classvar("classvar is now Parent");

local $\ = "\n";
sub puts ($) { print shift }

sub new {
    my $class = shift;

    my $self = {};
    $class = ref $class || $class;
    bless $self, $class;
    $self->init;
    $self;
}

sub init {
    my $self = shift;
    $self->name("default name");
}

sub set_for_read {
    shift->{for_read} = 'read only';
}

sub puts_for_write {
    puts shift->{for_write};
}

sub say_self {
    puts "i am Parent";
}

1;
Child.pm
package Child;

use strict;
use warnings;

use base qw/Parent/;
__PACKAGE__->classvar('classvar is now Child');

BEGIN {
    local $\ = "\n";
    print __PACKAGE__->classvar;
}

local $\ = "\n";
sub puts ($) { print shift }

sub say_self {
    my $self = shift;
    $self->SUPER::say_self(@_);
    puts "i am Child";
}

1;
main.pl
use strict;
use warnings;
use Data::Dumper;

use base qw/Child/;

local $\ = "\n";
sub puts ($) { print shift }

my $ch = Child->new;

puts $ch->name;
$ch->name('my name');
puts $ch->name;

$ch->say_self;

$ch->set_for_read;
puts $ch->for_read;

$ch->for_write('write only');
$ch->puts_for_write;

puts $ch->classvar;
実行
% perl main.pl
classvar is now Parent
default name
my name
i am Parent
i am Child
read only
write only
classvar is now Child

ruby

parent.rb
class Parent
  @@classvar = 'classvar is now Parent'
  def initialize
    @name = 'default name'
  end

  def say_self
      puts "i am Parent"
  end

  def set_for_read
    @for_read = 'read only'
  end

  def puts_for_write
    puts @for_write
  end

  attr_accessor :name
  attr_reader :for_read
  attr_writer :for_write
end
child.rb
require 'parent'

class Child < Parent
  puts @@classvar
  @@classvar = 'classvar is now Child'

  def say_self
    super
    puts 'i am Child'
  end

  def classvar
    puts @@classvar
  end
end

main.rb

require 'child'

ch = Child.new

puts ch.name
ch.name = 'my name'
puts ch.name

ch.say_self

ch.set_for_read
puts ch.for_read

ch.for_write = 'write only'
ch.puts_for_write

ch.classvar
実行
% ruby main.rb
classvar is now Parent
default name
my name
i am Parent
i am Child
read only
write only
classvar is now Child

えーと

  • perlのクラス変数があれでいいのか自信無し
  • rubyインスタンスからクラス変数の参照の仕方が分からなかったので、わざわざクラス変数をputsするだけのメソッド生やしたけど、これ多分頭悪い
  • 書き込み専用のメンバ変数の存在意義が分かりません
    • rubyだと書き込み専用でもインスタンスメソッド内で参照は可能だったが、perlだとそれすら駄目だったのでhashref直参照
  • perlオブジェクト指向に慣れてると、rubyオブジェクト指向で違和感を覚えた
    • perlだとセッタ使うときは $hoge->name('ore') とメソッドの引数で実現するが、rubyだと hoge.name = 'ore' と代入スタイル
      • まあメンバ変数って言うからにはrubyの方が自然なんだろう
  • 確かにrubyはスマートに書ける。perlは冗長というか、同じことを先頭に毎回書くのがめどい
    • Mooseはひとまず置いとけ
  • perlだとクラス名とファイル名は同じ。rubyではファイル名は小文字オンリー。これ超違和感