2013-05-20 3 views
1

Я только начал разрабатывать класс Perl, и мой единственный предыдущий опыт работы с OOP с C++ был давным-давно.Объекты Perl - инициализация переменной класса

Есть несколько элементов данных, которые мне нужны для «переменных класса» - общие для всех экземпляров. Я бы хотел, чтобы они были инициализированы до того, как я впервые создам объект, и мне бы хотелось, чтобы основная программа вызывала use MyClass, чтобы предоставить параметр для этого процесса инициализации.

Вот рабочий пример класса с переменным классом:

package MyClass; 
use strict; 
use warnings; 

# class variable ('our' for package visibility)                 
#                            
our $class_variable = 3; # Would like to bind to a variable              

sub new { 
    my $class = shift; 
    my $self = { }; 
    bless $self, $class; 
    return $self; 
} 

sub method { 
    my $self = shift; 
    print "class_variable: $class_variable\n"; 
    ++$class_variable; # prove that other instances will see this change           
} 

А вот это демо:

#!/usr/bin/perl                         

use strict; 
use warnings; 
use MyClass; 

my $foo = MyClass->new(); 
$foo->method(); # show the class variable, and increment it. 

my $bar = MyClass->new(); 
$bar->method(); # this will show the incremented class variable. 

Есть ли способ для основной программы, чтобы указать значение $ class_variable ? Значение будет известно во время компиляции в основной программе.

+0

Возможный дубликат [Как я могу установить статическую переменную, которая с доступ ко всем подклассам того же базового класса (Perl/Moose)?] (https://stackoverflow.com/questions/7587157/how-can-i-set-a-static-variable-that-can-be -accessed-by-all-subclasses-of-the) –

ответ

2

Использование import объекта:

package MyClass; 

my $class_variable; 

sub import 
{ 
    (undef, my $new_class_variable) = @_; 

    if (defined $class_variable and 
     defined $new_class_variable and 
     $class_variable ne $new_class_variable) 
    { 
    warn '$MyClass::class_variable redefined'; 
    } 

    $class_variable = $new_class_variable if defined $new_class_variable; 
} 

Пропустите если вы use модуль:

use MyClass qw(42); 

Это не совсем идиоматический Perl, но это тоже не редкость. Эта проверка здравомыслия в середине функции должна дать вам подсказку о том, почему это не лучший подход во всех случаях. Если MyClass только должен быть use d из сценария верхнего уровня, вы можете применять эту проверку вменяемости вместо:

caller eq 'main' or die 'MyClass can only be used from package main'; 
+0

Я вижу вашу точку зрения о возможности использования из другого пакета. В моем случае аргумент, который я хочу передать, - это имя программы, так что MyClass может читать некоторые метаданные для конкретной программы из базы данных. Определенно случай, когда имеет смысл использовать его только из 'main'. (Я думаю.) – Chap

+0

@Chap вы не можете использовать [$ 0] (http://search.cpan.org/~rjbs/perl-5.18.0/pod/perlvar.pod#$0)? – Oktalist

+0

Аргумент относится, точнее, к протоколу приложения, которое будет использоваться. Хотя в настоящее время существует взаимно однозначная взаимосвязь между программами и протоколами, я не хочу настаивать на этом. (Если это имеет смысл.) – Chap

2
$MyClass::class_variable = "some value"; 
6

Вы также можете сделать переменную «частный», объявив его my вместо our. В таком случае, вы должны предоставить метод класса для его инициализации:

my $class_variable = 3; 

sub initialize_variable { 
    my ($class, $value) = @_; 
    die "Ivalid value $value.\n" unless $value =~ /^[0-9]+$/; 
    $class_variable = $value; 
} 

, а затем в программе:

'MyClass'->initialize_variable(42); 
+0

Это выглядит хорошо. Я не думаю, что есть какой-либо способ использовать сам «использование», есть ли? например 'использовать MyClass qw/42 /;'? – Chap

+1

@Chap Если у MyClass есть подзаголовок 'import', это будет вызываться, когда perl встречает оператор' use' с этими аргументами: 'import (« MyClass », 42)' (см. [Import] (http: // perldoc .perl.org/functions/import.html), [use] (http://perldoc.perl.org/functions/use.html)) – Oktalist

+0

@ Окталист Красивый. Это на самом деле лучшее решение для моих целей, потому что оно гарантирует, что это происходит до создания какого-либо объекта. Если вы хотите ввести это в качестве ответа, я дам вам кредит на «правильный ответ». – Chap

0

Вы можете также использовать метод класса:

Ex:

package myclass; 

our $class_variable = 5; 

sub myclass_method{ 

    my ($class, $new_class_variable_value) = @_; 

    if($class_variable != $new_class_variable_value) 
    { 
     ## set the new value of the class/package variable 
     $class_variable = $new_class_variable_value; 
    } 
} 

В вашем сценарии вы бы ссылаться на это, выполнив:

myclass::myclass_method('myclass', 7); 

 Смежные вопросы

  • Нет связанных вопросов^_^