В чем разница между → и:: в Perl
Какова разница между ::
и ->
в Perl?
->
иногда работает там, где ::
нет.
Ответы
Ответ 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
Надеюсь, что это поможет.