in reply to Re: Passing the logger's object (updated)
in thread Passing the logger's object

Thank you for these examples!

In other words, it's okay to use some methods of the parental class, as it's not a crime, right?

V.Melnik
  • Comment on Re^2: Passing the logger's object (updated)

Replies are listed 'Best First'.
Re^3: Passing the logger's object (updated)
by stevieb (Canon) on Nov 13, 2016 at 20:59 UTC

    Absolutely having class methods/data is ok.

    This does not break encapsulation. You're simply calling the method on the class, instead of an instance (object) of the class.

    This in fact is quite common. Imagine you have a class that counts its objects. The count variable would be a class var, and you could just write a class method that returns that value. Note here that when writing class methods, you have to realize that the first param will be the module name, not a blessed instance, so you won't have $self to operate on.

    Class methods don't break encapsulation, and if you ever changed $count, you'd refactor the class method to return the right thing, instead of changing scripts that reference $Module::count directly.

    Class methods also provide you the ability to do things with a module without having to instantiate a new object:

    sub new { return bless {}, shift; } sub add { shift; # throw away object/class; not needed my ($x, $y) = @_; return $x + $y; }

    Now you can add() in either of these ways:

    my $res = Module->add(1, 2); # or my $obj = Module->new; my $res = $obj->add(1, 2); # or even my $mod = 'Module'; my $res = $mod->add(1, 2);

    I use the latter form of calling class methods in my unit tests, especially when creating numerous objects within the same test file:

    my $mod = 'My::Long::Module::Name'; { # test 1 my $obj = $mod->new; } { # test 2 my $obj = $mod->new; } # etc
Re^3: Passing the logger's object (updated)
by haukex (Archbishop) on Nov 14, 2016 at 10:16 UTC

    Hi v_melnik,

    If you're referring to my inheritance example Library::Bar, then no, it's not a crime and absolutely normal to call a method inherited from the parent class this way. A subclass is just a mixture of methods inherited from the parent, parent methods overridden by the subclass, and methods defined only in the subclass. Except for the case of a method in the parent class being intended to be completely private to the parent, the subclass's methods can call each other all they want.

    If you're referring to my Library::Foo example of calling a class method, then again no, any class is free to call any other class's (public) class methods - the most common example of a class method is new! The disadvantage of class methods is that they don't operate on individual objects, which in your example would mean that the class method that hands out the logger object could not hand out different Library::Logger objects based on different Library instances. You may not need to do so at the moment, but perhaps you might decide in the future you'd like to do so, hence an instance method would be more extensible.

    Just as an aside, in Perl, it's easy to write a method that can be used both as a class and an instance method, since the only difference between the two is that a class method gets the name of the class it was called on as its first argument, while an instance method gets the object as its first argument. Also note how inheritance works in the following example:

    package Foo; sub new { bless {}, shift } sub foo { my $self = shift; if (ref $self) { print "Instance method called on $self\n"; } else { print "Class method called on class $self\n"; } } package Bar; use parent -norequire, 'Foo'; package main; Foo->foo; # "Class method called on class Foo" Foo->new->foo; # "Instance method called on Foo=HASH(0x...)" Bar->foo; # "Class method called on class Bar" Bar->new->foo; # "Instance method called on Bar=HASH(0x...)"

    Hope this helps,
    -- Hauke D