2016-03-06 4 views
1

Мне нужен способ сделать действительно инкапсулированные переменные в Perl, без использования каких-либо фреймворков, таких как Moose, чтобы вы могли обращаться к переменным экземпляра только через getters и seters. Должны быть частные переменные экземпляра.Парадигмы OO и инкапсулированные переменные экземпляра в Perl5

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

Есть ли способ предотвратить это?

+0

Я отредактировал ваш вопрос, чтобы сделать его более читаемым. Убедитесь, что он по-прежнему верен. Но, боюсь, я никогда не слышал об этом. переменная *; Что ты имеешь в виду? – Borodin

+0

Это была ошибка, там нет ни одного. вары. То, что я имею в виду, это то, что вы всегда можете вызвать perl-переменную throw имя пакета (имя класса) и в то же время бросать экземпляр, и это, например, в Java невозможно, переменная экземпляра - это переменная экземпляра и класс переменная - это переменная класса, возможно, я немного отказался от своего вопроса, поэтому, чтобы завершить ее, я хотел бы иметь реальную переменную частного экземпляра в perl. –

+0

@DenisKomnenovic s/throw/through/если я не ошибаюсь. Отредактировал ваш Q. – laune

ответ

-2

Чтобы сделать действительно частные переменные, которые вы должны использовать замыкания:

{ 
    my $x; 

    sub get { 
     return $x; 
    } 

    sub set { 
     $x = shift; 
    } 
} 

set(3); 
print get(); # prints 3 
print $x; # ERROR 

# Example with objects 
package Class; 

sub new { 
    bless {}, 'Class'; 
} 
{ 
    my $storage = {}; 

    sub get { 
     $self = shift; 
     return $storage->{ "$self" };    
    } 

    sub set { 
     $self = shift; 
     $storage->{ "$self" } = shift; 
    } 
} 

package main; 
print Class::x; #ERROR 

$z = Class::new(); 
$z->set(3); 

$y = Class::new(); 
$y->set(5); 
print $y->get(); # 5 
print $z->get(); # 3 

$x является локальным по отношению к блоку. Ни один из них, кроме set и get, может получить к нему доступ.
«$ self» будет выглядеть как «Class = HASH (0x1cf9160)». Из-за того, что каждый объект имеет свой собственный адрес в памяти, «$ self» никогда не столкнется.

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

+0

Это выглядит красиво, спасибо за совет. Но я все еще проблема, что я могу назвать эту переменную, используя имя пакета (имя класса), но я хотел бы иметь реальную частную переменную «экземпляр». Теперь я, возможно, должен определить геттеры таким образом, чтобы они просто разрешали вызов ссылки/экземпляра. Eugen благодарит за проезд. –

+0

Ваши 'set' и' get' не являются методами, и даже если вы позволите забыть написать 'my $ self = shift', то ваш $ x является переменной * класса * тот же класс – Borodin

+0

@DenisKomnenovic: Нет, вы не можете получить доступ к переменным, объявленным с помощью 'my', используя пакет. Они не являются переменными пакета. Пожалуйста, объясните, какую проблему вы пытаетесь решить. Вы надеетесь защитить себя от хакеров или просто плохо программировать? – Borodin

3

Это звучит, как вы пытаетесь, чтобы помешать людям получить доступ к экземплярам переменных, отличные через аксессор ; это правильно?

Perl - это язык для вежливых людей, и то, как вы прекращаете программистам делать то, что вам не нужно, это попросить их не делать этого. Да, есть хаки, и наиболее очевидным здесь было бы сделать каждый объект закрытием (here's an article about it from the Perl Journal), но вокруг них почти всегда есть способы, поэтому вы не сможете остановить решительного дерзкого хакера

1 от Larry Wall's excellent attributions - это, что объясняет мою точку превосходно.

У Perl нет увлечений с соблюдением конфиденциальности. Он предпочел бы, чтобы вы остались вне его гостиной, потому что вы не были приглашены, не потому, что у него есть дробовик

+0

Может кто-то * пожалуйста, дайте мне знать, если журнал Perl не доступен для свободного доступа? Я был удивлен, что не смог найти «правильный» общедоступный URL для своего контента. Спасибо – Borodin

+0

Конков и Бородин: Спасибо, ребята, вы мне очень помогаете, с этими небольшими ответами. Я пытаюсь внедрить в Perl какой-то вид netbeans-соглашения и фабричный шаблон и другие вещи, как я бы сделал на Java и без каких-либо фреймворков. Конечно, прямо не так, как на Java, но теперь вы понимаете, что я имею в виду. Благодарю. –

+1

@DenisKomnenovic: Мне жаль, что вы никогда не хотели объяснять, чего вы надеялись достичь. Это явно проблема [XY] (http://xyproblem.info/), но нам никогда не давали возможность решить основную проблему, и у вас были очень расплывчатые ответы, когда нам приходилось угадывать в ваших целях. – Borodin

2

Люди пытались достичь такого рода вещи с наизнанку объектами. This presentation by David Golden объясняет это прекрасно:

  • изнутри наружу предметы первой представленные голландской Perl хакера Абигейл в 2002

  • Весна 2002 - Первое упоминание в Amsterdam.pm,

  • 28 июня, 2002 - YAPC NA «Два альтернативных способа проведения ОО»

  • 1 июля 2002 г. - Первое упоминание о Perlmonks

  • Получил недавнее внимание (известность?) В качестве рекомендуемой наилучшей практики с публикацией Дамиана Конвея Perl Best Practices

  • Несмотря на их преимущества, они приносят значительную сложность и не повсеместно приветствуются

Есть целый number of modules, которые пытаются облегчить этот тип программирования.

Я нахожу их довольно громоздкими, и с тех пор они выпали из положения.

Вы также можете найти их упоминается в perldoc perlobj:

В прошлом сообщество Perl экспериментировал с техникой, называемой «внутри-из объектов». Объект out-out хранит свои данные вне ссылки на объект, индексируется по уникальному свойству объекта, например адресу памяти, а не самому объекту. Это имеет преимущество, заключающееся в обеспечении инкапсуляции атрибутов объекта, поскольку их данные не хранятся в самом объекте.

Этот метод был популярен некоторое время (и был рекомендован в лучших практиках Дамиана Конвей Перла), но так и не получил всеобщего усыновления. Модуль Object::InsideOut на CPAN обеспечивает всестороннюю реализацию этого метода, и вы можете увидеть его или другие модули с наименьшим из них в дикой природе.