在Perl上创建一个类(class :: Std)

Tho*_*mas 1 perl constructor reference class std

我在寻求你对Perl的帮助.

我目前通过创建一个新对象然后使用它来运行一个函数来使我的代码运行良好,但我想使用更新的Perl编码方式(使用class:Std和集成BUILD/ START函数)

所以现在我的代码看起来像这样,我调用new一个日志文件的路径,然后运行一个函数:

# Called from another perl script
use MyClass;
my $Obj = MyClass->new('/usr/me/path.log');
$Obj->run();

# My module
package MyClass;

sub new {
    shift if ( defined($_[0] eq 'MyClass') );
    my %args  = validate( @_,{ LogPath => { type => SCALAR, optional => 0 }, } );

    my $self;
    $self->{plistPath} = $_[1];
    return bless $self;
}

sub run {
    my $self = shift;
    ...
    ...
}
Run Code Online (Sandbox Code Playgroud)

而我想拥有的是这样的事情:

use Class::Std

sub BUILD {
    my $self = shift;
    my $ident = shift;

    my %args  = validate( @_, { LogPath => { type => SCALAR, optional => 0 }, } );

    print "My log path:".$args{LogPath}."\n";

    $self->{logPath} = $args{LogPath};

    return bless $self;
}

sub run {
    my $self = shift;

    print $self->{logPath};

    ....
}
Run Code Online (Sandbox Code Playgroud)

但这不起作用,它打印好日志路径BUILD(我只是想检查它是否有效),但我无法让它注册路径$self->{logPath}以在我的其他功能中使用它.它告诉我它不是哈希引用.

从我已经完成的教程中,我认为BUILD不应该返回$self它自动创建的Class::Std,但我不知道该怎么做.

如果您有任何建议,我们将非常感谢您的帮助.

蒂姆,非常感谢.

xxf*_*xxx 5

由于您正在学习更现代的风格,我可能会建议您尝试使用MooseMoo,因为它们会尝试简化面向对象的perl体验,因为我们会让它变得更强大.这些模块在推出之后Class::Std就被引入,并代表了一种更现代的创建对象的方法.Moose/Moo(以及其他一些,如MoM(笑话))之间的区别在于Moose 为您提供了对象元编程的全部功能,而Moo则力求更低的功率,但速度更快.

以下是使用Moo的代码示例:

test.pl

#!/usr/bin/env perl

use strict;
use warnings;

use MyClass;
my $obj = MyClass->new(LogPath => '/var/log/messages');
$obj->run();
1;
Run Code Online (Sandbox Code Playgroud)

MyClass.pm

package MyClass;
use Moo; # Moose / Mouse / Moo

has LogPath => (
    is => 'ro',    # Read Only
    required => 1, # Required
    isa => sub {
        my ($path) = @_;
        die "LogPath must be a SCALAR" if (ref $path);
        die "LogPath [$path] must be a real path" unless -f $path;
    },
);

sub run {
    my ($self) = @_;
    print "MyClass::run()\n";
    my $path = $self->LogPath();
    print "About to do something with LogPath [ $path ]\n";
}

1;
Run Code Online (Sandbox Code Playgroud)

产量

perl test.pl
MyClass::run()
About to do something with LogPath [ /var/log/messages ]
Run Code Online (Sandbox Code Playgroud)

根据要求,为了进行比较,这里是同一个对象,但这次是使用Class :: Std创建的.请注意Class::Std解决方案需要多少代码/样板Moo:

test_class_std.pl

#!/usr/bin/env perl

use strict;
use warnings;

use MyClassStd;
my $obj = MyClassStd->new({ LogPath => '/var/log/messages' });
$obj->run();
print $obj->get_description() . "\n";
Run Code Online (Sandbox Code Playgroud)

MyClassStd.pm

package MyClassStd;

use Class::Std;

# Create storage for object attributes...
# The syntax '%foo : ATTR' applies the attribute named ATTR to the hash %foo.
# For more info on how this works, see: perldoc attributes

# Create one hash per attribute, these will be private to the class
my %log_paths   : ATTR;

# These fields will be available via $obj->get_foo() methods
my %public_data : ATTR;

# Handle initialization of objects of this class...
sub BUILD {
    my ($self, $object_id, $args) = @_;
    my $path = check_path( $args->{ LogPath } );
    $log_paths{ $object_id } = $path;
    $public_data{ $object_id }{ description } = "LogPath is set to [ $path ]";
}

# Handle cleanup of objects of this class...
sub DEMOLISH {
    my ($self, $object_id) = @_;
    # Objects will be removed from the hashes automatically
    # Add any other cleanup code here
}

# Handle unknown method calls...
sub AUTOMETHOD {
    my ($self, $object_id, @args) = @_;

    my $method_name = $_; # Method name passed in $_
    # Return any public data...
    if ( $method_name =~ m/^get_(.*)/ ) {
        my $get_what = $1;
        return sub {
            return $public_data{$object_id}{$get_what};
        }
    }

    warn "Can't call $method_name on ", ref $self, " object";

    return; # The call is declined by not returning a sub ref
}

sub run {
    my ($self) = @_;

    print "MyClassStd::run()\n";
    my ($path) = $log_paths{ ident $self };
    print "About to do something with LogPath [ $path ]\n";

}

sub check_path {
    my ($path) = @_;

    die "LogPath must be a SCALAR" if ( ref $path );
    die "LogPath [ $path] must be a real path" unless -f $path;

    return $path;
}

1;
Run Code Online (Sandbox Code Playgroud)

产量

MyClassStd::run()
About to do something with LogPath [ /var/log/messages ]
LogPath is set to [ /var/log/messages ]
Run Code Online (Sandbox Code Playgroud)

  • 并消灭鼠标:) (2认同)