In OOP (Object Oriented Programming), getter is the generic name for any method that will return the value of one of the attributes of the current instance.

setter is the generic name of any method that will set the value of one of the attributes.

It is clear that a getter needs to return the value of the attribute, but what should a setter return?

There are a number of options.

Setter returns nothing (undef)

One of the possibilities is that the setter will return "nothing". As there is no real "nothing" in Perl, this means the function needs to return undef.

There are two ways to do this either by calling return undef; or by calling return; without providing anything. In the "Perl Best Practices" book Damian Conway recommended the latter and thus Perl::Critic has a policy to prohibit explicit return undef, but in fact both have its advantages and disadvantages.

I won't go in the details here, let's just see the two examples:

Setter explicitly returns undef

examples/oop/setter/return_undef.pm



sub field {
   my ($self, $value) = @_;
   if (@_ == 2) {
       $self->{field} = $value;
       return undef;
   }
   return $self->{field};
}

Setter returns nothing (undef or empty list)

examples/oop/setter/return_nothing.pm



sub field {
   my ($self, $value) = @_;
   if (@_ == 2) {
       $self->{field} = $value;
       return;
   }
   return $self->{field};
}

When to use this: I think this should be the default way to implement setters with an explicit call to return with or without passing undef. This will create the smallest problem if and when you decide to return some other value.

If you don't call return at all then the function will return the result of the last statement which will change as you change the implementation of the code. The problem with leaving out the explicit call to return is that when users of this module notice that the setter returns a certain value, they will start to rely on it even if the documentation says the return value is meaningless. Then when you decide to go with one of the explicit return values, or if you change the implementation that also changes the last statement in the function, the code using this module will break and they will blame you.

It is better to return nothing (or undef).

Return the currently assigned value

examples/oop/setter/return_current.pm


sub field {
   my ($self, $value) = @_;
   if (@_ == 2) {
       $self->{field} = $value;
   }
   return $self->{field};
}

The idea here is consistency. Both the 'getter' and the 'setter' return the current value of the 'attribute'.

This will allow the "stacking" of the setter call on top of one ore more assignments: Just as we can stack simple assignments:

my $name = my $fname = 'Foo';

We can also use the call to the 'setter' (which is basically just an assignment) at the end of the statement.

my $name = my $fname = $obj->name('Foo');

Return the previous value

examples/oop/setter/return_previous.pm


sub field {
   my ($self, $value) = @_;
   if (@_ == 2) {
       my $old = $self->{field};
       $self->{field} = $value;
       return $old;
   }
   return $self->{field};
}


Instead of writing code like this:

my $old = $obj->name;
$obj->name('Foo');
...
$obj->name($old);

The users of our class can save one line:

my $old = $obj->name('Foo');
...
$obj->name($old);

There are some examples for similar behavior in core perl.

The delete function return the value of the hash key being deleted. The one-parameter version of the select function returns the previously selected filehandle.

Return the instance object for chained method calls

In this case the setter will return the instance itself.

examples/oop/setter/return_instance.pm


sub field {
   my ($self, $value) = @_;
   if (@_ == 2) {
       $self->{field} = $value;
       return $self;
   }
   return $self->{field};
}



This sounds useless, after all we already had the object somehow, probably in a variable, but this will let the users chaining method calls.

For example some of the methods of Path::Iterator::Rule work like this as showing in the last example of finding files in a directory tree.

It is also probably confusing as the reader and writer of the code where this is used can only differentiate between getter and setter by the presence or lack of presence of a parameter. This compounded by the fact the using it as a getter or as a setter will return different things might be confusing and thus might be the source of errors.

In the implementation inside the if-condition we return $self, the instance, while outside the if-condition we return $self->{field}, the current value of the field.