Perl模块方法调用:不能在$ {SOMEFILE}行$ {SOMELINE}的未定义值上调用方法"X"

hey*_*hew 6 perl module function dbi

到处都是,特别是在DBI中,我看到这个消息一直出现.令人困惑的是,因为首先想到的是我传递函数的参数被设置为undef(或类似的东西),但显然不是这样.

给定一个模块和相应的脚本......

模块: ./lib/My/Module.pm

package My::Module;

use strict;
use warnings;

sub trim {
    my $str = shift;
    $str =~ s{ \A \s+ }{}xms; # remove space from front of string
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string
    return $str;
}
Run Code Online (Sandbox Code Playgroud)

脚本: ./test.pl

#!/usr/bin/perl

use strict;
use warnings;
use My::Module qw(trim);

print $My::Module->trim( " \t hello world\t \t" );
Run Code Online (Sandbox Code Playgroud)

我收到了错误消息

无法在./text.pl第7行的未定义值上调用方法"trim".

事实上,如果我调用$My::Module->notamethod( "hello world" );它会产生类似的错误.

上面的脚本/模块出了什么问题?

这个错误Can't call method “X” on an undefined value at ${SOMEFILE} line ${SOMELINE}真的在说什么?这是指方法调用的上下文(在这里传递给print),还是参数的上下文?

Dav*_*oss 13

你正在混淆几种不同的方法来处理模块和对象 - 最后是一个不起作用的方法.

以下是四种有效的方法:

1/My :: Module是一个库.修剪不会导出.

$ cat My/Module.pm 
package My::Module;

use strict;
use warnings;

sub trim {
  my $str = shift;

  $str =~ s{ \A \s+ }{}xms; # remove space from front of string
  $str =~ s{ \s+ \z }{}xms; # remove space from end of string
  return $str;
}

1;
$ cat test 
#!/usr/bin/perl

use strict;
use warnings;

use My::Module;

# Note: No $ and :: not ->
print My::Module::trim( " \t hello world\t \t" );
Run Code Online (Sandbox Code Playgroud)

2/My :: Module是一个库.修剪出口.

$ cat My/Module.pm 
package My::Module;

use strict;
use warnings;

use Exporter;
our @ISA    = qw(Exporter);
our @EXPORT = qw(trim);

sub trim {
  my $str = shift;

  $str =~ s{ \A \s+ }{}xms; # remove space from front of string
  $str =~ s{ \s+ \z }{}xms; # remove space from end of string
  return $str;
}

1;
$ cat test 
#!/usr/bin/perl

use strict;
use warnings;

use My::Module;

print trim( " \t hello world\t \t" );
Run Code Online (Sandbox Code Playgroud)

3/MyModule是一个类.trim是一种类方法.

$ cat My/Module.pm 
package My::Module;

use strict;
use warnings;

sub trim {
  # Note class name passed as first argument
  my $class = shift;
  my $str = shift;

  $str =~ s{ \A \s+ }{}xms; # remove space from front of string
  $str =~ s{ \s+ \z }{}xms; # remove space from end of string
  return $str;
}

1;
$ cat test 
#!/usr/bin/perl

use strict;
use warnings;

use My::Module;

# Note: Not $ and -> not ::
print My::Module->trim( " \t hello world\t \t" );
Run Code Online (Sandbox Code Playgroud)

4/MyModule是一个类,trim是一个对象方法.

$ cat My/Module.pm 
package My::Module;

use strict;
use warnings;

# Need a constructor (but this one does nothing useful)
sub new {
  my $class = shift;

  return bless {}, $class;
}

sub trim {
  # Note: Object method is passed an object (which is ignored here)
  my $self = shift;
  my $str = shift;

  $str =~ s{ \A \s+ }{}xms; # remove space from front of string
  $str =~ s{ \s+ \z }{}xms; # remove space from end of string
  return $str;
}

1;
$ cat test 
#!/usr/bin/perl

use strict;
use warnings;

use My::Module;

my $trimmer = My::Module->new;

print $trimmer->trim( " \t hello world\t \t" );
Run Code Online (Sandbox Code Playgroud)

我认为您正在尝试选项1.在这种情况下,我认为我建议选项2.

并回答你的最后一个问题.您收到该错误是因为您尝试在未定义的变量($ My :: Module)上调用方法.


yst*_*sth 6

该语法在变量中查找对象或类名$My::Module并调用其trim方法,但该变量未定义.

相反,你只想说print My::Module::trim( " \t hello world\t \t" );调用My :: Module :: trim()函数.

从使用行看,您似乎正在尝试将trim()导入到本地包中,因此您可以在没有My::Module::限定条件的情况下调用它,但您的模块看起来不像是为了支持导出而设置的.

在你的正则表达式中,/ s和/ m标志没有任何效果 - 它们只改变.,^和$匹配,并且你不使用任何这些.