Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> OOP, private 
V
    Опции темы
Jlekc
  Дата 24.1.2006, 00:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 520
Регистрация: 10.2.2005
Где: Leopolis

Репутация: нет
Всего: 4



собственно сабж

Как описуються приваты для екземпляров класса?
В частности переменная должна быть масивом.

ЗЫ: сорри, за глупый вопрос. Просто первый день сижу в перле.


--------------------
PM MAIL ICQ   Вверх
DEER
Дата 24.1.2006, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 749
Регистрация: 12.4.2005
Где: г. Рязань

Репутация: 1
Всего: 13



вроде чтобы переменная была приват, её надо начать со знака подчеркивания "_", хотя это для функций....
я спрашивал раньше, почитай, может поможет http://forum.vingrad.ru/index.php?showtopic=70947
Добавлено @ 10:45
Цитата(korob2001)

Отрываем "Perl - специальный справочник" Стивен Холзнер (страница 357) и читаем.

Создание приватных методов и данных

Хотя многие объектно-ориентированные языки программирования поддерживают приватные методы и переменные ( то есть внутренние методы и переменные, не достижимые вне класса или объекта ), Perl не позволяет делать этого явно.

Вы всегда можете использовать переменные с лексической областью видимости (ключевое слово my), что бы ограничить область видимости переменных текущим пакетом.

Что бы создать приватные переменные, надо воспользоваться следующим соглашением Perl: приватные имена начинаются с символа подчёркивания. В отличии от языков типа C++, Java или Delphi, это не значит, что вы не може получить доступ к приватным переменным и методам объекта. Идея состоит в том, что если имя начинается с символа подчёркивания, его не следует использовать, поскольку оно считается приватным. В следующем примере публичный ( открытый ) метод sum исплользует приватный ( закрытый ) метод _add для сложения двух велечин:
.....



--------------------
 
PM MAIL WWW ICQ MSN   Вверх
Jlekc
Дата 24.1.2006, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 520
Регистрация: 10.2.2005
Где: Leopolis

Репутация: нет
Всего: 4



2DEER хмм, чот линк не грузиться.

Сорри перемудрил с постановкой задачи. Мне не обезательно делать приваты.
Мне нужно чтоб переменная пренадлежала екземпляру.
Сейчас понял как сделать статики (our), a 'my' как понял относиться только к области видимости отдельной функции.

Это сообщение отредактировал(а) Jlekc - 24.1.2006, 12:27


--------------------
PM MAIL ICQ   Вверх
korob2001
Дата 24.1.2006, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 31
Всего: 61



Привет! Я не совсем понял постановки зададачи, но думаю тебя интересует следующее.
Код

package MyClass;

# Коструктор
sub new {
       my $ch = shift;
       my $class = ref( $ch ) || $ch;
       my $self   = [ qw(ONE TWO THREE) ];
       return bless($self, $class);
}

# метод добавляет один елемент в конец массива
sub setElement {
       my $self = shift;
       push( @{$self}, shift );
}

# Метод извлекает первый елемент массива
sub getElement {
       my $self = shift;
       return @{$self} ? shift @{$self} : undef;
}

1;

$self = это и есть наш массив екземпляра, точнее ссылка на массив.

Теперь о my и our.
Раз уж речь пошла о закрытости в классах, то давай и рассмотрим пример с классом.
Для примера, давай создадим класс и тестовый файл, который будет использовать наш класс:
Файл: MyClass.pm
Код

package MyClass;

my @private_array = qw(ONE TWO THREE);
our @public_array = qw(A B C D);

# конструктор
sub new {
    my $ch    = shift;
    my $class = ref($ch) || $ch;
    my $self  = {};
    return bless($self, $class);
}

# Метод возвращает массив @private_array
sub getPrivateArray {
    return @private_array;
}

# Метод добавляет новый элемент в конец массива
sub pushLast {
    push(@private_array, $_[1]);
}

# Метод добавляет новый елемент в начало массива
sub pushFirst {
    unshift(@private_array, $_[1]);
}

# Метод возвращает длину массива
sub getLength {
    return scalar @private_array;
}

# Метод возвращает размер массива в байтах
sub getSize {
    my $size = 0;
    $size += length( $_ ) for @private_array;
    return $size;
}

1;

Файл: test.pl
Код

#!/usr/bin/perl -w
use strict;
# Ищем модули и классы в текущем каталоге
use lib qw(.);
# Подключаем класс
use MyClass;

# Создаём объект
my $cls = new MyClass();

# Получаем массив и выводим его в STDOUT
print join(", ", $cls->getPrivateArray()), "\n";

# Посмотрим размер массива
print "Now in array " . $cls->getLength() . " elements (" . $cls->getSize() . " bytes)\n";

# Просто разделитель
print "=" x 60, "\n";

# Добавляем новый элемент в конец массива
$cls->pushLast("FOUR");

# Получаем массив и выводим его в STDOUT
print join(", ", $cls->getPrivateArray()), "\n";

# Посмотрим размер массива
print "Now in array " . $cls->getLength() . " elements (" . $cls->getSize() . " bytes)\n";

# Просто разделитель
print "=" x 60, "\n";

# Добавляем новый элемент в начало массива
$cls->pushFirst("ZERO");

# Опять выводим массив
print join(", ", $cls->getPrivateArray()), "\n";

# Посмотрим размер массива
print "Now in array " . $cls->getLength() . " elements (" . $cls->getSize() . " bytes)\n";

# Просто разделитель
print "=" x 60, "\n";

# Пробуем обратиться к массиву напрямую, а не через методы доступа
# Работать не будет, так как переменные объявленные как my, имеют
# лексическую область видимости. Для теста раскоментируй следующую строку
# print "Close array: " . join(", ", @MyClass::private_array) . "\n";

# Попробуем теперь таким же способом вывести открытый массив, объявленный как our
print "Open array: " . join(", ", @MyClass::public_array) . "\n";

Здесь стоит обратить внимание на то, что массив @private_array имеет лексическую область видимости, т.е. к нему имеют доступ все методы которые находятся с ним в одном пакете. Если нужна ещё более сильная закрытость, то можно захватить в блок, массив и методы для работы с ним. Тогда доступ к нему будут иметь только те методы, которые находятся вместе с ним в одном блоке ( в одной лексической области видимости ). Для примера попробуем немного изменить код класса MyClass. Сохрани следующий класс и тестовый файл в одном каталоге:
Файл: MyClass2.pm
Код

package MyClass2;

our @public_array = qw(A B C D);

# конструктор
sub new {
    my $ch    = shift;
    my $class = ref($ch) || $ch;
    my $self  = {};
    return bless($self, $class);
}

###########################################################
{  # Начинается  блок, т.е. новая лексическая область видимости
   # Всё, что объявлено здесь как my не видно за пределами
   # этой области.

   # Наш массив
   my @private_array = qw(ONE TWO THREE);

   # Метод возвращает массив @private_array, этот метод видит наш, закрытый, массив.
   sub getPrivateArray {
       return @private_array;
   }

   # Метод возвращает длину массива, этот метод видит наш, закрытый, массив
   sub getLength {
       return scalar @private_array;
   }

   # Метод возвращает размер массива в байтах, этот метод тоже видит наш, закрытый, массив
   sub getSize {
       my $size = 0;
       $size += length( $_ ) for @private_array;
       return $size;
   }
} # Закончился блок. Всё, что находится за пределами этого блока, не имеет
  # доступа к тому, что объявлено внутри блока как my.
###########################################################


# Метод добавляет новый элемент в конец массива, этот  метод не имеет доступа к
# массиву @private_array
sub pushLast {
    if ( @private_array ) {
         # добавим в конец закрытый массив новый элемент
         push(@private_array, $_[1]);
    } else {
         # в противном случае добавим этот элемент в конец открытого массива
         push(@public_array, $_[1]);
    }
}

# Метод добавляет новый элемент в начало массива, этот  метод не имеет доступа к
# массиву @private_array
sub pushFirst {
    if ( @private_array ) {
         # Добавим в начало массива @private_arraу новый елемент
         unshift(@private_array, $_[1]);
    } else {
         # в противном случае добавим этот элемент в начало открытого массива
         unshift(@public_array, $_[1]);
    }
}

1;

Файл: test2.pl
Код

#!/usr/bin/perl -w
use strict;
# Ищем модули и классы в текущем каталоге
use lib qw(.);
# Подключаем класс
use MyClass2;

# Создаём объект
my $cls = new MyClass2();

# Получаем массив и выводим его в STDOUT
print join(", ", $cls->getPrivateArray()), "\n";

# Посмотрим размер массива
print "Now in array " . $cls->getLength() . " elements (" . $cls->getSize() . " bytes)\n";

# Просто разделитель
print "=" x 60, "\n";

# Добавляем новый элемент в конец массива
$cls->pushLast("FOUR");

# Получаем массив и выводим его в STDOUT
print join(", ", $cls->getPrivateArray()), "\n";

# Посмотрим размер массива
print "Now in array " . $cls->getLength() . " elements (" . $cls->getSize() . " bytes)\n";

# Просто разделитель
print "=" x 60, "\n";

# Добавляем новый элемент в начало массива
$cls->pushFirst("ZERO");

# Опять выводим массив
print join(", ", $cls->getPrivateArray()), "\n";

# Посмотрим размер массива
print "Now in array " . $cls->getLength() . " elements (" . $cls->getSize() . " bytes)\n";

# Просто разделитель
print "=" x 60, "\n";

# Пробуем обратиться к массиву напрямую, а не через методы доступа
# Работать не будет, так как переменные объявленные как my, имеют
# лексическую область видимости. Для теста раскоментируй следующую строку
# print "Close array: " . join(", ", @MyClass2::private_array) . "\n";

# Попробуем теперь таким же способом вывести открытый массив, объявленный как our
print "Open array: " . join(", ", @MyClass2::public_array) . "\n";

Заметь, что все элементы, были добавлены в открытый массив, а не в закрытый. Теперь к закрытому массиву имеют доступ только 3 метода getPrivateArray(), getLength() и getSize(). Если вынести массив из блока, на старое место, то новые элементы будут добавлены в закрытый массив, а не в открытый.
Те методы, которые находятся внутри блока, в нашем случае это getPrivateArray(), getLength() и getSize(), имеют доступ как к отрытому массиву, так и к закрытому. Просто в нашем случае они этого не делают, не потому, что не получится, а потому, что не было нужды. Для эксперимента, добавь в блок, в классе MyClass2.pm, ещё два метода:
Код

   # Метод возвращает общее кол-во элементов в обоих массивах
   sub getTotalLength {
       return @public_array + @private_array;
   }

   # Метод возвращает общий размер в байтах, обоих массивов
   sub getTotalSize {
       my $size = 0;
       $size += length($_) for (@public_array, @private_array);
       return $size;
   }

А в тестовую программу test2.pl добавь, в конец следующие строки:
Код

# Просто разделитель
print "=" x 60, "\n";

# Покажем общее кол-во элементов обоих массивов и их размер в байтах
print "Total elements = " . $cls->getTotalLength() . " (" . $cls->getTotalSize() . " bytes)\n";

На самом деле, добавление новых методов в лексическую область, было излишним. Можно было бы вынести их за пределы лексической области и сделать так, что бы они были более универсальны. Давай попробуем сделать это.
Вынеси теперь последние 2 метода (getTotalLength() и getTotalSize()), за пределы блока, сохранись и попробуй запустить тестовый файл.
Результат будет будет не верным, точнее он будет показывать нам лишь размер массива @public_array. Для того, что бы всё это заработало вне лексической области видимости массива, воспользуемся уже существующими методами доступа. Теперь давай поправим наши, последние, два метода (getTotalLength() и getTotalSize()), следующим образом:
Код

# Метод возвращает общее кол-во елементов в обоих массивах
sub getTotalLength {
    my $self = shift;
    # Получаем кол-во элементов массива @private_array, через метод доступа,
    # определённый ранее в той же лексической области, что и массив @private_array
    return @public_array + $self->getLength();
}

# Метод возвращает общий размер в байтах, обоих массивов
sub getTotalSize {
    my $self = shift;
    my $size = 0;
    # Узнаём размер массива @public_array
    $size += length($_) for (@public_array);
    # Узнаём размер массива @private_array, через метод доступа, который определили
    # ранее в той же лексической области, что и массив @privete_array и возвратим общее
    # кол-во байт
    return $size + $self->getSize();
}

Теперь мы получим правильное значение, не зависимо от того, расположены они (методы) в одной лексической области с массивом @private_array или вне этой области.

Но учти, что такой массив не является членом экземпляра, все изменения которые ты будешь делать, будут отражаться и на других объектах этого класса, т.е. если изначально создать два объекта, после вносить какие либо изменения через один объект, а в конце вывести общее кол-во елементов через оба объекта, то результаты будут одинаковы. Если тебе нужно, что бы каждый объект хранил свои идивидуальные члены то тебе нужен первый способ, который я привёл вначеле. Этот же способ более подходит для создания так называемых приватных методов. Т.е. ты объявляешь переменную, как my, а присваиваешь ей ссылку на подпрограмму.
Код

my $private_method = sub {
      # тело метода
}

Как ты уже наверное догадался, мы получим закрытый метод, который нельзя вызвать из вне пакета, а точнее той лексической области видимости, к которой он относится. Его так же можно захватить в блок, причём глубина блоков может быть любой.

Что касается символа подчёркивания _, в начале имени метода, то это лишь соглашение, что такой метод считается закрытым и его вызывать из вне не нужно.

Вот что пишет Ларри Уолл о закрытости, в книге "Программирование на Perl":
Цитата

Perl не требует, что бы вы придерживались какого-то определённого стиля программирования, и не одержим идеей закрытости, как некоторые другие объектно-ориентированные языки программирования. Однако Perl одержим идеей свободы, и одна из свобод, которые Perl предоставляет программисту, это право избрать такую меру закрытости, какую он пожелает. На самом деле, Perl может обеспечить более сильную закрытость в своих классах и объектах, чем C++. Это означает, что Perl ни в чём не ограничивает программиста и, в частности, не ограничивает его право ограничивать самого себя (если вас занимают такого рода вещи).


Это сообщение отредактировал(а) korob2001 - 24.1.2006, 13:56


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Jlekc
Дата 24.1.2006, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 520
Регистрация: 10.2.2005
Где: Leopolis

Репутация: нет
Всего: 4



2korob2001 зачет. Спасибо, разабрался.

Первый вариант меня вполне устраивает. Но и остальное было полезно почитать.


--------------------
PM MAIL ICQ   Вверх
korob2001
Дата 24.1.2006, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 31
Всего: 61



Кстати, вот пример первого варианта, где каждый объект имеет свой екземпляр массива:
Файл: MyClass3.pm
Код

package MyClass3;

# Коструктор
sub new {
       my $ch = shift;
       my $class = ref( $ch ) || $ch;
       my $self   = [ qw(ONE TWO THREE) ];
       return bless($self, $class);
}

# метод добавляет один елемент в конец массива
sub setElement {
       my $self = shift;
       push( @{$self}, shift );
}

# Метод извлекает первый елемент массива
sub getElement {
       my $self = shift;
       return @{$self} ? shift @{$self} : undef;
}

sub getArray {
    my $self = shift;
    return wantarray ? @{$self} : scalar @{$self};
}

1;

Файл: test3.pl
Код

#!/usr/bin/perl -w
use strict;
use lib qw(.);
use MyClass3;

# Создаём три объекта
my $cls1 = new MyClass3;
my $cls2 = new MyClass3;
my $cls3 = new MyClass3;

# Добавляем по одну элементу в каждый экземпляр
$cls1->setElement("From first object");
$cls2->setElement("From second object");
$cls3->setElement("From third object");

# Выводим содержимое каждого экземпляра
print "First object: "  . join(", ", $cls1->getArray()), "\n";
print "Second object: " . join(", ", $cls2->getArray()), "\n";
print "Third object: "  . join(", ", $cls3->getArray()), "\n";

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

Это сообщение отредактировал(а) korob2001 - 24.1.2006, 14:29


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
Jlekc
Дата 24.1.2006, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 520
Регистрация: 10.2.2005
Где: Leopolis

Репутация: нет
Всего: 4



2korob2001 на '+' нарываемся7))


--------------------
PM MAIL ICQ   Вверх
korob2001
Дата 24.1.2006, 14:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 31
Всего: 61



smile Уже нарвался.


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.3327 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.