1

很抱歉很含糊,但我不知道这个概念的名称。我会尽力解释。我会试着把它放在动物的角度来简化它。

我有一个通用的超类。这个超类包含所有动物都必须做的功能。例如,我不想在每个动物子类中重新定义“take_breath”子类,所以我在 Animals 超类中定义一次,所有动物(Animals::Cat、Animals::Dog 和 Animals::Llama)都可以简单地访问 $self->take_breath()。这些动物也经历了许多相同的初始化例程,而不是每次我简单地调用 $class->SUPER::new(@_) 以及做特定于该动物的事情时都重新定义它们。

话虽如此,每次初始化动物时,它都会经历其超类的初始化例程。有数百只动物,它们运行了数百次。这不是太大的问题。

然而,这些动物很聪明,并且知道如何使用 LWP::UserAgent 网络浏览器。为了访问互联网,他们必须登录网页并设置会话 cookie。他们都共享相同的登录名并希望共享相同的浏览器。在我当前的实现中,登录例程是超类新方法的一部分。这意味着当动物被初始化时,它会运行并且动物登录。正如我所说,我有数百只动物并且不想触发数百个 POST 请求。我想以某种方式启动登录例程并使其成为超类的一部分。然后每只动物都可以通过 $self->{'ua'} 访问“共享”网络浏览器。

我希望这能解释它,我不确定这个 OOP 术语叫什么。

TLDR 适合那些不喜欢动物的人

我在超类中有一个登录例程,它创建 LWP::UserAgent、登录并设置会话 cookie。子类都可以共享一个登录名。我不想为每个子类触发数百个 POST 请求来登录。我想以某种方式登录一次并与所有子类共享准备好的 $ua 对象。

4

1 回答 1

2

有两种方法可以解决这个问题:

1.包变量

不是每个动物实例都有一个 UA,但 UA 是作为动物的一部分。您可以在启动时初始化 UA。动物可以通过访问器或变量访问 UA:

package Animal;

my $ua = LWP::UserAgent->new();

sub ua { $ua }

接着

my $ua = $self->ua();

或者

package Animal;

our $ua = LWP::UserAgent->new();

接着

my $ua = $Animal::ua;

对此的技术术语是类变量,或者在 Java静态方法静态变量等语言中。

Java 翻译:

class Animal {
  private static LWP.UserAgent ua = new LWP.UserAgent();
  public static LWP.UserAgent getUa() { return ua }
  ...
}

class Animal {
  public static LWP.UserAgent ua = new LWP.UserAgent();
  ...
}

2.state变量

在较新的 Perls (>= v5.10?) 中,您可以使用state. 他们声明词法变量。该变量在程序的生命周期内初始化一次,而不是每次执行语句时(就像使用 一样my)。

use feature 'state';
package Animal;
sub new {
  my ($class, %args) = @_;
  state $ua = LWP::UserAgent->new;
  bless { ua => $ua, %args } => $class;
}

接着

my $ua = $self->{ua};

do使用块执行更广泛的初始化可能很有用

state $ua = do {
  my $ua = LWP::UserAgent->new;
  ...;
  $ua;
};

或将初始化卸载到子中:state $ua = make_ua();

如果您必须针对较早的 perls,您可以将newsub 包含在单独的范围内,并在那里将变量声明为词法以获得类似的效果:

package Animal;

{
  my $ua = LWP::UserAgent->new;
  sub new {
    my ($class, %args) = @_;
    bless { ua => $ua, %args } => $class;
  }
}

这里唯一的区别是UA的初始化时间。(当然还有烦人的大括号的数量。)初始化可以推迟,正如Len Jaffe提到的:

package Animal;

{
  my $ua; # just declare scope here
  sub new {
    my ($class, %args) = @_;
    $ua ||= LWP::UserAgent->new;  # $ua is false until initialized
    bless { ua => $ua, %args } => $class;
  }
}

因为对象是引用,所以所有动物都会得到相同的 UA。

特别是在 C/C++ 中,这也称为静态变量state修饰符可以看作是一个非 OO 单例构造函数。

于 2013-06-21T17:21:23.853 回答