Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Damn it, Perl can't bless my object

Tags:

perl

bless

Puns aside, I'm trying to implement an import method in my Perl class to instantiate a Data object, which is essentially a glorified array of hashrefs, from a proper array of hashrefs.

Here's an example of how I plan to use it:

# Pull in the data
my $data = Data->import(
                         [
                           { a => 1, b => 7, c => 3},
                           { a => 7, b => 9, c => 2},
                         ]
                       );

$data->manipulate;  # Use package methods

My import implementation is as follows:

package Data;

sub initialize {
    my $class = shift;
    my $data = [];
    bless $data, $class;
    return $data;
}

sub import {

    my ( $class, $data ) = @_;

    bless $data, $class;
    return $data;
}

1;

The surprising thing is that Perl reports the error at compile-time (note the BEGIN block):

Can't bless non-reference value at Data.pm line 51.
BEGIN failed--compilation aborted at myScript.pl line 8.

perldiag didn't add much clarity to what's going on:

Can't bless non-reference value

(F) Only hard references may be blessed. This is how Perl "enforces" encapsulation of objects. See perlobj.


I even tried initializing the object and adding the data in two separate steps:

sub import {                         #< Another constructor >

    my ( $class, $data ) = @_;

    my $obj = $class->initialize;
    push @$obj, @$data;

    return $obj;
}

This resulted in the following compile-time error:

Can't use an undefined value as an ARRAY reference...
BEGIN failed--compilation aborted at...

Two questions:

  1. What's wrong with what I've done?
  2. Could someone please clarify the perldiag explanation of this compile-time error?
like image 287
Zaid Avatar asked Sep 11 '11 09:09

Zaid


1 Answers

import() is a dangerous name to give a method, as Perl sometimes calls a method called 'import' for you. In fact, the statement:

use Data;

really means:

BEGIN {
    require Data;
    Data->import();
}

which happens during 'compilation'.

So it's likely that your import() method is being called by Perl as part of the class loading mechanism before you get a chance to use it. You should rename your import() method to something else (e.g. import_data) and you should be fine.

like image 69
Alex Avatar answered Oct 19 '22 12:10

Alex