【问题标题】:Multiple data members in a perl classperl 类中的多个数据成员
【发布时间】:2014-12-05 06:47:46
【问题描述】:

我是perl 的新手,还在perl 中学习oop。我通常在C、C++ 中编码。需要bless一个对象通知perl先搜索那个包里的方法。这就是祝福的作用。然后在-> 的帮助下进行的每个函数调用都将instance 本身作为第一个参数传递。现在我对为新对象编写构造函数有疑问。通常构造函数通常看起来像:

sub new {
    my %hash = {};
    return bless {%hash};    #will automatically take this package as the class
}

现在我想在我的班级中有两个数据成员,这样我就可以做这样的事情:

sub new {
    my %hash = {};
    $hash->{"table_header"} = shift @_;   #add element to hash
    $hash->{"body_content"} = shift @_;
    return bless {%hash};    #will automatically take this package as the class
}

我的问题是这是唯一可能的方法。我们不能像C 和C++ 那样拥有多个数据成员,而且我们必须使用像“table_header”和“body_content”这样的字符串。

编辑: 在 C 或 C++ 中,我们可以直接引用数据成员(现在假设它是公共的)。这里有一个额外的参考。我想知道是否有任何方法可以让我们拥有 C 这样的对象。

sub new {
    my $table_header = shift @_;
    my $body_content = shift @_;
    #bless somehow
}

希望这能消除一些困惑。

【问题讨论】:

  • 我不明白你的困惑。在 Perl 中,“对象”是一个有福的散列。对象的属性是存储在散列中的值,键是属性名称。您还在寻找什么?
  • 你是指带有函数的对象类,还是带有成员的对象类? (即一个提供功能,另一个提供数据)
  • @JimGarrison 请查看编辑。
  • @nrathaus 具有成员(多个成员)的对象类。函数可以是多个。
  • @JimGarrison:Perl 对象是对任何事物的祝福reference。它从不祝福哈希:你不能祝福哈希。

标签: perl oop


【解决方案1】:

有些模块使 Perl 中的 OOP 变得更容易。最重要的是Moose:

use strict; use warnings;

package SomeObject;
use Moose; # this is now a Moose class

# declare some members. Note that everything is "public"
has table_header => (
  is => 'ro', # read-only access
);
has body_content => (
  is => 'rw', # read-write access
);

# a "new" method is autogenerated

# some method that uses these fields.
# Note that the members can only be accessed via methods.
# This guards against typos that can't be easily caught with hashes.
sub display {
  my ($self) = @_;
  my $underline = "=" x (length $self->table_header);
  return $self->table_header . "\n" . $underline . "\n\n" . $self->body_content . "\n";
}

package main;

# the "new" takes keyword arguments
my $instance = SomeObject->new(
  table_header => "This is a header",
  body_content => "Some body content",
);

$instance->body_content("Different content"); # set a member

print $instance->display;

# This is a header
# ================
# 
# Different content

如果您了解 Moose,您会发现一个比 Java 或 C++ 灵活得多的对象系统,因为它借鉴了 Perl6 和 Common Lisp 对象系统的思想。当然,这很丑陋,但在实践中效果很好。

由于 Perl OOP 的工作方式,不可能将实例成员作为变量单独访问。嗯,差不多。有一个实验性的 mop 模块可以做到这一点。

use strict; use warnings;
use mop;

class SomeObject {
  # Instance variables start with $!..., and behave like ordinary variables
  # If you make them externally accessible with "is ro" or "is rw", then
  # appropriate accessor methods are additionally generated.

  # a private member with public read-only accessor,
  # which has to be initialized in the constructor.
  has $!table_header is ro = die 'Please specify a "table_header"!';

  # a private member with public read-write accessor,
  # which is optional.
  has $!body_content is rw = "";

  # new is autogenerated, as in Moose

  method display() {
    # arguments are handled automatically, so we could also do $self->table_header.
    my $underline = "=" x (length $!table_header);
    return "$!table_header\n$underline\n\n$!body_content\n";
  }
}

# as seen in Moose
my $instance = SomeObject->new(
  table_header => "This is a header",
  body_content => "Some body content",
);

$instance->body_content("Different content"); # set a member, as in Moose

print $instance->display;

# This is a header
# ================
# 
# Different content

虽然它有很好的语法,但现在不要将mop 用于严肃的项目,而是坚持使用 Moose。如果 Moose 对你来说太重了,那么你可能会喜欢更轻的替代品,比如 Mouse 或 Moo(这三个对象系统大多相互兼容)。

【讨论】:

    【解决方案2】:

    您对 哈希 和 哈希引用 感到困惑。您还忘记了任何方法的第一个参数是对象引用或包的名称。 Perl 构造函数像任何其他方法一样被继承,因此您必须将新对象放入正确的包中,以使多态性正常工作。这段代码是你想要的

    sub new {
      my $package = shift;
      my %self;
      $self{table_header} = shift;
      $self{body_content} = shift;
      bless \%self, $package;
    }
    

    我不清楚你所说的“直接引用数据成员”是什么意思,但是如果你希望你可以避免在任何地方写$self,这样每个变量都隐含地是哈希的一个元素那么你不能。 Perl 比大多数语言灵活得多,并且可以使用 any 祝福引用作为对象实例。最常见的是使用散列,但偶尔引用数组、标量甚至文件句柄更合适。这种灵活性的代价是在您指代祝福散列的成员时准确指定。我不认为这是太大的负担。

    您始终可以更简洁地编写代码。上面的方法可以写成

    sub new {
      my $package = shift;
      my %self;
      @self{qw/ table_header body_content /} = @_;
      bless \%self, $package;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-18
      • 2013-03-03
      相关资源
      最近更新 更多