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

Разница между моим и нашим? (объявлено в том же файле)

Прежде чем писать эту программу, я подумал, что our - это переменная области пакета, а my - переменная области файла. Но после этой программы я запутался.

Моя программа,

#!/usr/bin/perl

use strict;
use warnings;

package one; 
our $val = "sat";
my $new = "hello";
print "ONE:val =>$val \n";
print "ONE:new =>$new \n\n";

package two;
print "TWO:val =>$val \n";
print "TWO:new =>$new \n";

который выводит

ONE:val =>sat 
ONE:new =>hello 

TWO:val =>sat 
TWO:new =>hello 

Итак, в чем разница между my и our. Оба они одинаковы или имеют какую-либо разницу?

4b9b3361

Ответ 1

Как вы видите, оба my и our имеют лексический эффект.

my создает лексически ограниченную переменную.

our создает лексически ограниченный псевдоним для переменной пакета.

Просто потому, что вы говорите package ни в коем случае не меняет лексическую область, поэтому ваш $val по-прежнему является псевдонимом $one::val даже после просмотра инструкции package two.

Если вы не видите близкого курчавого, вы не закончили свой охват. (Или EOF или конец строки в строке eval).

Ответ 2

my ограничивает доступ переменных к самому внутреннему блоку, в котором они были объявлены. Если блока нет, они ограничены файлами.

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

package pack;
our $variable;    # These are the same
$pack::variable;  # These are the same

наша переменная является чем-то похожей на статическую переменную C, но отличается тем, что переменная, объявленная с помощью нашей в функции, все еще доступна вне функции, если она вызывается с переменным полным именем.

Но больше всего my имеет лексическую область, а наша - лексическая область, но их жизнь сохраняется даже вне блока объявления (их жизнь похожа на глобальную переменную жизнь), поэтому чтобы действительно понять разницу между my и нашим, вам нужно понять разницу между лексическим и глобальным областями в Perl.

Вкратце разница между двумя типами:

Глобальные переменные

Любой код в любом месте может изменять свои значения.

Лексические переменные

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


Чтобы ответить на конкретный пример-вопрос: попробуйте переместить второе объявление пакета (пакет два) в другой файл, и вы увидите разницу между my и наш...

Ответ 3

Важно различать видимость и время жизни.

Видимость переменных, объявленных с использованием our или my, идентична. Вы можете использовать имя в любом месте после объявления до первой закрывающей скобки или конца файла.

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

$pack::three = 3;

и использовать его где угодно в любом пакете. Мне даже не нужно объявлять пакет pack. Но если я пишу

package pack;
our $three;

Я создал сокращенный псевдоним для $pack::three, который я могу использовать в той же лексической области, что и переменная my в том же месте: перед закрывающей скобкой или концом файла.

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

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

В вашем коде вы создали псевдоним $val для переменной пакета $one::val и лексическую переменную $new. Они также не входят в кодовый блок, поэтому оба они видны до конца файла. package two не имеет никакого эффекта здесь, но если вы написали our $val после этого второго оператора пакета, вы бы изменили псевдоним $val, указав вместо него $two::val.

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