Подтвердить что ты не робот

В чем разница между → и:: в Perl

Какова разница между :: и -> в Perl?

-> иногда работает там, где :: нет.

4b9b3361

Ответ 1

:: имеет два применения.

  • Это разделитель пространства имен в именах пакетов

    use Foo::Bar;    # Load Foo/Bar.pm
    $Foo::Bar::var   # $var in namespace Foo::Bar
    
  • При добавлении к годовому слову он создает строковый литерал [1].

    Ниже приведено значение 'hello', за исключением того, что он предупреждает, что пакет hello не существует:

    hello::
    

-> имеет два применения.

  • Используется для разыменования.

    $array_ref->[$i]
    $hash_ref->{$k}
    $code_ref->(@args)
    
  • Он используется в вызовах метода для обозначения invocant.

    CGI->new()        # Static method call
    $cgi->param()     # Object method call
    

Вероятно, вы спрашиваете, в чем разница между

Foo::Bar::mysub()

и

Foo::Bar->mysub()

Первый вызов функции. Последний вызов метода. Вызов метода похож на вызов функции с двумя отличиями:

  • Вызов метода использует наследование.

  • Вызов метода передает invocant (то, что осталось от ->) в sub в качестве первого аргумента.

{
   package Foo::Baz;
   sub new {
      my ($class, $arg) = @_;
      my $self = bless({}, $class);
      $self->{arg} = $arg;
      return $self;
   }

   sub mysub1 {
      my ($self) = @_;
      print($self->{arg}, "\n");
   }
}

{
   package Foo::Bar;
   our @ISA = 'Foo::Baz'; 
   sub mysub2 {
      my ($self) = @_;
      print(uc($self->{arg}), "\n");
   }
}

my $o = Foo::Bar->new('hi');  # Same as: my $o = Foo::Baz::new('Foo::Bar', 'hi');
$o->mysub1();                 # Same as: Foo::Baz::mysub1($o);
$o->mysub2();                 # Same as: Foo::Bar::mysub2($o);

Примечания

  • Foo->method обманчиво называет sub под именем Foo, если он существует (используя его значение, которое он возвращает как invocant). Foo::->method, что означает 'Foo'->method, нет.

Ответ 2

Когда правая сторона является функцией ->, она передает свою левую сторону в качестве первого аргумента функции. Таким образом, следующие примеры эквивалентны, если $foo - объект, благословленный пакетом Foo, и Bar находится в пакете Foo. -> разрешает унаследованные методы, делая его более чистым и более полезным для объектов.

$foo->Bar();

Foo::Bar($foo);

-> также может принимать имя пакета

Foo->Bar();

Foo::Bar('Foo');

Это означает, что -> обычно используется в методах экземпляра, так что объект передается его самим и конструкторам, поэтому конструкторы знают, какой пакет будет благословлять. Обычно это параметр, поэтому он может быть унаследован.

Ответ 3

Здесь много объяснений, но вот очень упрощенный ответ для новых разработчиков:

FOO::BAR();  # is calling the class (aka. package's) default object
$FOO->BAR(); # is calling an initiated object

Объект обычно имеет свойства, которые часто устанавливаются, где в качестве непосвященного объекта используются только свойства объекта по умолчанию.

Say FOO имеет свойство "Age", значение по умолчанию которого 1, которое мы можем изменить с помощью команды set ранее в нашей программе. Затем мы решили снова вызвать пакет в обоих направлениях для удовольствия:

use FOO;
$FOO = new FOO(); #new instance of foo 
$FOO->SetAge(21);

# more code here

print $FOO->GetAge(); # prints 21
print FOO::GetAge(); # prints 1

Как насчет пакетов без каких-либо хранимых переменных? Во многих случаях вообще не может быть никакой разницы, но это в конечном счете зависит от того, как написан класс. В конце концов, это сложнее, чем это... и это не совсем точный ответ, но я считаю, что вы ищете на основе вашего вопроса.

Просто, чтобы предотвратить путаницу, я вообще не использую имя классов/пакетов при создании объекта. Если по какой-то причине я не знаю, как это назвать, я префикс его "o", поэтому ясно, что это объект, а не класс, который является хорошей практикой для любого языка программирования.

то есть. используйте

$oFOO = new FOO(); // new object instance of foo

Надеюсь, что это поможет.