Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Translating Perl to Ruby - modules vs. classes

Namespacing in Perl is pretty straight forward, but I can't seem to find a solution for translating this very simple Perl class hierarchy to Ruby.

Perl

lib/Foo.pm

package Foo;

use Foo::Bar;

sub bar {
    return Foo::Bar->new()
}

lib/Foo/Bar.pm

package Foo::Bar

sub baz {}

main.pl

use Foo;
my $foo = Foo->new();
my $bar = $foo->bar();
$bar->baz()

Ruby

Modules can't be instantiated, so this code obviously won't work:

lib/foo.rb

require 'foo/bar.rb'

module Foo    
  def bar
    Foo::Bar.new
  end
end

lib/foo/bar.rb

module Foo
  class Bar
    def baz
    end
  end
end

main.rb

require 'lib/foo.rb'
foo = Foo.new
bar = foo.bar
bar.baz

But trying to declare Foo as a class instead doesn't work either, because there's already a module by that name:

lib/foo.rb:3:in `<top (required)>': Foo is not a class (TypeError)

So I end up with:

lib/foo.rb

module Foo
  class Foo
    ...
  end
end

main.rb

foo = Foo::Foo.new

Which is just not what I want. I have the feeling that I'm missing something very fundamental. :) Thanks for shedding some light on this.

like image 688
daskraken Avatar asked Apr 23 '15 22:04

daskraken


1 Answers

In Ruby, both modules and classes can be used to provide namespace separation. In fact Class is a subclass of Module, and most things you can do with a Module you can also do with a Class

If Foo needs to be a class, declare it as a class, don't declare it as a module.

E.g.

lib/foo.rb

require 'foo/bar.rb'

class Foo    
  def bar
    Foo::Bar.new
  end
end

lib/foo/bar.rb

class Foo
  class Bar
    def baz
    end
  end
end

main.rb

require 'lib/foo.rb'
foo = Foo.new
bar = foo.bar
bar.baz
like image 119
Neil Slater Avatar answered Nov 16 '22 14:11

Neil Slater