代码之家  ›  专栏  ›  技术社区  ›  Ether

Perl中的new some::class和some::class->new()有什么区别?

  •  27
  • Ether  · 技术社区  · 16 年前

    许多年前,我记得有一个程序员同事在咨询:

    new Some::Class;    # bad! (but why?)
    
    Some::Class->new(); # good!
    

    可悲的是,现在我记不起他为什么这样做了。:(两个窗体都将正常工作,即使构造函数实际上不存在于some::class模块中,而是从某个父级继承的。

    这两种形式都与某些::class::new()不同,后者不会将类的名称作为第一个参数传递给构造函数——因此,此形式总是不正确的。

    即使这两种形式是等效的,我也发现有一些::class->new()更加清晰,因为它遵循在模块上调用方法的标准约定,在Perl中,“new”方法不是特殊的-构造函数可以被调用任何东西,new()可以做任何事情(当然,我们通常希望它是一个构造函数)。

    4 回复  |  直到 10 年前
        1
  •  26
  •   friedo    16 年前

    使用 new Some::Class 被称为“间接”方法调用,这很糟糕,因为它在语法中引入了一些歧义。

    它失败的一个原因是如果您有一个对象数组或散列。你可能会想到

    dosomethingwith $hashref->{obj}
    

    等于

    $hashref->{obj}->dosomethingwith();
    

    但实际上它分析为:

    $hashref->dosomethingwith->{obj}
    

    这可能不是你想要的。

    另一个问题是,如果包中有一个函数的名称与您试图调用的方法的名称相同。例如,如果某个模块 use 'd导出了一个调用 dosomethingwith ?在那种情况下, dosomethingwith $object 不明确,可能导致令人困惑的错误。

    使用 -> 语法排他性地消除了这些问题,因为编译器总是清楚方法和您希望方法操作的内容。

        2
  •  21
  •   Community arnoo    7 年前

    Indirect Object Syntax 在Perlobj文档中解释它的缺陷。 freido's answer 包括其中一个(尽管我倾向于避免在函数调用周围使用显式parens)。

    拉里曾经开玩笑说,这是为了让C++感到高兴。 new 尽管人们会告诉你永远不要使用它,但你可能一直在这样做。考虑一下:

    print FH "Some message";
    

    你有没有想过我的文件句柄后面没有逗号?在间接对象表示法中,类名后面没有逗号?这就是发生的事情。您可以将其重写为打印时的方法调用:

    FH->print( "Some message" );
    

    你可能在 print 如果你做错了。在显式文件句柄后加逗号将使其变为参数:

    print FH, "some message";     # GLOB(0xDEADBEEF)some message
    

    遗憾的是,我们在Perl中使用了这种GoogleFiness。并不是所有进入语法的东西都是最好的主意,但当你从这么多的资源中寻找灵感时,就会发生这种情况。有些想法一定是坏的。

        3
  •  4
  •   Sam Kington    16 年前

    有充分的理由,不赞成使用间接对象语法,但这与构造函数无关。在调用包中几乎永远不会有新的()函数。相反,您应该将package->new()用于另外两个(更好?)原因:

    1. 如您所说,所有其他类方法都采用package->method()的形式,因此一致性是一件好事。

    2. 如果您正在向构造函数提供参数,或者您正在获取构造函数的结果并立即对其调用方法(例如,如果您不关心保持对象在周围),则更简单地说,例如。

    $foo = Foo->new(type => 'bar', style => 'baz');
    Bar->new->do_stuff;
    

    $foo = new Foo(type => 'bar', style => 'baz');
    (new Bar)->do_stuff;
    
        4
  •  -3
  •   Shawn H Corey    16 年前

    另一个问题是 new Some::Class 在运行时发生。如果存在错误,并且您测试从不分支到该语句,那么在生产环境中发生之前,您永远不会知道它。最好用一下 Some::Class->new 除非你在做动态编程。