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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Классы, работа с данными 
:(
    Опции темы
Bulat
Дата 1.10.2007, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



Вообщем-то раньше писал на яве, сейчас пишу на перле, но очень хочется порой писать по ООП'ному, просто так красивее и проще smile

Просмотрел ряд топиков, но все же...

Хочется решить такую задачу:

Есть класс, в нем инкапсулированные переменные класса, и методы getVariable1, getVariable2 и т.д., а также методы setVariable1, setVariable2 и т.д.
Все переменные должны поступать через конструктор класса, т.е. методы setVariable1  и т.д. только для правки. smile

Т.е. по сути дела класс - лишь контейнер для хранения данных. 

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

Вообще видел один не плохой топик, однако то, что меня в нем не устроило, то, что там массив был внутри самого экземпляра класса. Мне же нужно чтоб класс был лишь "контейнером". Т.е. каждый экземпляр класса хранить по одному набору переменных объявленных в классе. А все экземпляры класса хранятся в массиве, скажем так основного скрипта. При прохождении данного массива обращаемся каждый раз к очередному экземпляру класса и работаем с переменными из данного экземпляра...

Надеюсь понятно выразился... smile




--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
korob2001
Дата 1.10.2007, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Ну насколько я понял, нужно что-то типа этого:

Есть класс Person, поля которого хранят имя, фамилию и возраст человека. Опишем его:

Файл Person.pm
Код

package Person;

# Конструктор класса Person
sub new {
    my $check = shift;
    my $class = ref($check) || $check;
    my $self  = {
        # Поля класса
        NAME => "",   # Имя - Значение по умолчанию, пустая строка
        FAMILY => "", # Фамилия - Значение по умолчанию, пустая строка
        AGE => 0,     # Возраст - Значение по умолчанию, 0
        @_,           # Присвоим полученный список
    };

    # Посвящаем ссылку в объект и возвращаем его
    return bless($self, $class);
}

################################################################################
# Методы доступа                                                               #
################################################################################

# Метод возвращает имя человека
sub getName {
    return shift->{NAME};
}

# Метод возвращает фамилию человека
sub getFamily {
    return shift->{FAMILY};
}

# Метод возвращает возраст человека
sub getAge {
    return shift->{AGE};
}

# Метод меняет имя человека
sub setName {
    my $self = shift;
    $self->{NAME} = shift if scalar @_;
}

# Метод меняет фамилию человека
sub setFamily {
    my $self = shift;
    $self->{FAMILY} = shift if scalar @_;
}

# Метод меняет возраст человека
sub setAge {
    my $self = shift;
    $self->{AGE} = shift if scalar(@_) && $_[0] > 0;
}

################################################################################
# Имитируем перегруженный метод. Если метод получает число, оно прибавляется   #
# к возрасту, если же метод был вызван без параметров, то добавляем к возрасту #
# единицу.                                                                     #
################################################################################
sub addAge {
    my $self = shift;
    my $add  = (scalar(@_) && ($_[0] =~ /^\d+$/) && ($_[0] > 0)) ? shift : 1;
    $self->{AGE} += $add;
}

1;

Теперь сохраним в тот же каталог, файл который будет использовать наш класс Person.

Файл people.pl
Код

#!/usr/bin/perl -w
use strict;
use Person;

# Создаём массив объектов Person
my @people = (
    new Person(NAME => "Вася", FAMILY => "Пупкин", AGE => 16),
    new Person(NAME => "Коля", FAMILY => "Герасимов", AGE => 12),
    new Person(NAME => "Валя", FAMILY => "Брусникина", AGE => 20)
);

# Пройдём по всему массиву и покажем информацию о каждом человеке
foreach my $person (@people) {
        print "Имя: " . $person->getName() . "\n";
        print "Фамилия: " . $person->getFamily() . "\n";
        print "Возраст: " . $person->getAge() . "\n\n";
}

# Следующая строка, просто разделитель
print "=" x 80, "\n";

################################################################################
# Теперь можно добавим каждому по одному году используюя метод addAge() без    #
# параметров. И снова покажем весь список.                                     #
################################################################################
for (my $i=0; $i < scalar(@people); $i++) {
     # Я намеренно использовал цикл for с переменной - счётчиком,
     # так, для разнообразия.
     $people[$i]->addAge();
}

################################################################################
# Покажем заново всех людей из нашего массива, так как нам массив дальше не    #
# понадобится, то обнуляем массив и попутно выводим информацию окаждом клиете  #
################################################################################
while (my $person = shift @people) {
       print "Имя: " . $person->getName() . "\n";
       print "Фамилия: " . $person->getFamily() . "\n";
       print "Возраст: " . $person->getAge() . "\n\n";
}

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

while (my $person = shift @people) {

Вставь наример такую:
Код

foreach my $person (@people) {

После этого цикла все объекты так и будут храниться в нашем массиве @people и будет возможность поэксперементировать с ним ещё. Например можно попробовать добавить каждому человеку не по одному году, а по 5 лет используя всё тот же метод addAge() но уже с одним параметром типа int.
Код

$person->addAge(5);

Здесь параметры получаемые конструктором получились именованные, если же хочешь сделать так, как в Java, то в конструкторе используй анонимный массив вместо анонимного хеша.

Но это так, простейший пример, если хочешь более подробно, то поищи в разделах по Perl, по ключевому слову "ООП" или "Объектно Ориентированное Программирование", а так же советую почитать книгу "Программирование на Perl", в ней автор языка более подробно описывает данную тему. Если знаком с Java, то думаю всё будет понятно.

Это сообщение отредактировал(а) korob2001 - 1.10.2007, 21:06


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


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



korob2001, супер.... Это даже больше чем я ожидал...

Есть только пара вопросов, чтоб добить это

Код

# Конструктор класса Person
sub new {
    my $check = shift;
    my $class = ref($check) || $check;
    my $self  = {
        # Поля класса
        NAME => "",   # Имя - Значение по умолчанию, пустая строка
        FAMILY => "", # Фамилия - Значение по умолчанию, пустая строка
        AGE => 0,     # Возраст - Значение по умолчанию, 0
        @_,           # Присвоим полученный список
    };

    # Посвящаем ссылку в объект и возвращаем его
    return bless($self, $class);
}


Я так понял, объявление переменных внутри класса, инкапсулирует их ???

И как бы так грамотнее выразится... $self и будет являтся экземпляром класса ???

И послдений пока вопрос:

Код

    new Person(NAME => "Вася", FAMILY => "Пупкин", AGE => 16),


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

$name = "Вася"
$family = "Пупкин"
$age = 16

new Person($name, $family, $age)


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

Добавлено через 13 минут и 32 секунды
Млин, прям все это так глаз радует, все эти старые геттеры и сеттеры, методы и классы, и все на перле..... Море восторга, и соотв...


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
Bulat
Дата 2.10.2007, 09:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



М-дя, и в догонку очень важный вопрос о деструкторах... В яве-то их ручками писать не надо, а как насчет перла ??


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
nitr
Дата 2.10.2007, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

Репутация: 37
Всего: 84



Bulat, тоже самое "не надо", но это исходя из задачи. В данном примере - не нужен.

А korob2001 как всегда smile обучает народ. Молодец! ;)


--------------------
PM   Вверх
Bulat
Дата 2.10.2007, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



nitr

А хорошего ;) , ресурса про ООП в перле случаем нет... А то в рамках данного примера все гуд, вот только хотелось более полно догнать такие вещи как наследование, инкапсуляция и т.п. 

P.S. Ссылки на топики форума прошу не кидать, в целом почти все промсотрел, но хотелось бы более полного материала smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
cerf_machine
Дата 2.10.2007, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Инкапсуляции в перле нет. Т.е. в представленном выше примере можно обращаться к "свойствам" "объекта" напрямую:

Код

my $person = new Person;

$person->{NAME} = "o___O";


Наследование в перле не использовал, но знаю, что оно тоже, к сожалению, псевдо, как и перегрузка операторов:( Реализуется через подключение базового класса в @ISA дочернего.

Цитата

И как бы так грамотнее выразится... $self и будет являтся экземпляром класса ???

Ага. Но на самом деле $self - ссылка на хэш, связанная (blessed) с текущим пакетом (Person). Свойства же - на самом деле - ключи хэша.
Цитата

При таком объявлении, возможно не соблюдение последовательности ???

Да, возможно.

Это сообщение отредактировал(а) cerf_machine - 2.10.2007, 14:41
PM MAIL ICQ   Вверх
korob2001
Дата 2.10.2007, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Bulat @  2.10.2007,  06:00 Найти цитируемый пост)
Я так понял, объявление переменных внутри класса, инкапсулирует их ???


Как сказал cerf_machine, инкапсуляция отсутсвует, как таковая, это философия Perl. Но, Perl позволяет сделать закрытость ещё более надёжную, чем другие языки программирования, разумеется, если это нужно.   smile 

Например можно таким образом изменить класс Person, который я приводил выше.
Код

package Person;

# Конструктор класса Person
sub new {
    my $check = shift;
    my $class = ref($check) || $check;

    # Поля класса
    my $fields = {
        NAME => "",
        FAMILY => "",
        AGE => 0, @_
    };

    my $self = sub {
        my $field = shift;
        my $f = (caller)[1];

        # Если запрос сделан не из текущего файла, умираем с музыкой
        die "This class using only private fields. For get or set value to " .
            "private fields, use access methods get/setName(), " .
            "get/setFamily(), get/setAge()." unless $f eq __FILE__;

        $fields->{$field} = shift if (@_);
        return $fields->{$field};
    };

    # Посвящаем ссылку в объект и возвращаем его
    bless($self, $class);
    return $self;
}

################################################################################
# Методы доступа                                                               #
################################################################################

# Метод возвращает имя человека
sub getName {
    shift->("NAME");
}

# Метод возвращает фамилию человека
sub getFamily {
    return shift->("FAMILY");
}

# Метод возвращает возраст человека
sub getAge {
    return shift->("AGE");
}

# Метод меняет имя человека
sub setName {
    my $self = shift;
    $self->("NAME", @_) if scalar @_;
}

# Метод меняет фамилию человека
sub setFamily {
    my $self = shift;
    $self->("FAMILY", @_) if scalar @_;
}

# Метод меняет возраст человека
sub setAge {
    my $self = shift;
    $self->("AGE", @_) if scalar(@_) && $_[0] > 0;
}

################################################################################
# Имитируем перегруженный метод. Если метод получает число, оно прибавляется   #
# к возрасту, если же метод был вызван без параметров, то добавляем к возрасту #
# единицу.                                                                     #
################################################################################
sub addAge {
    my $self = shift;
    my $add  = (scalar(@_) && ($_[0] =~ /^\d+$/) && ($_[0] > 0)) ? shift : 1;
    $self->("AGE", $self->("AGE") + $add);
}

1;

Вот собственно мы и закрылись, теперь поля доступны только внутри файла Person.pm, т.е. мы получили private поля. Можно так же сделать и protected, ну или что-то похожее на protected поля в Java, если изменить условие в конструкторе:
Код

        my $f = (caller)[1];

        # Если запрос сделан не из текущего файла, умираем с музыкой
        die "This class using only private fields. For get or set value to " .
            "private fields, use access methods get/setName(), " .
            "get/setFamily(), get/setAge()." unless $f eq __FILE__;

на такое:
Код

        my($p,$f) = caller;

        # Если запрос сделан не из текущего пакета или не из наследника, умираем с музыкой
        die "This class using only protected fields. For get or set value to " .
            "private fields, use access methods get/setName(), " .
            "get/setFamily(), get/setAge()." if (($p ne __PACKAGE__) || !$p->isa(__PACKAGE__))

Т.е. напрямую к полям теперь можно будет обращаться только из текущего пакета или же из классов наследников. Можно так же реализовать и закрытые методы, опять же, если это нужно.

Цитата(Bulat @  2.10.2007,  06:00 Найти цитируемый пост)
и тут главное соблюдат правильную последовательность переменных... При таком объявлении, возможно не соблюдение последовательности ???

Абсолютно верно, потому использовать анонимный хеш гораздо удобнее, не следует думать о перегрузке конструктора. Если же хочешь создать аналог создания Java или C++ объекта, то вместо анонимного хеша используй анонимный массив:

Вот так теперь будет выглядеть наш класс Person.pm
Код

package Person;

# Конструктор класса Person
sub new {
    my $check = shift;
    my $class = ref($check) || $check;

    my $self = [ @_ ];

    return bless($self,$class);
}

################################################################################
# Методы доступа                                                               #
################################################################################

# Метод возвращает имя человека
sub getName {
    shift->[0];
}

# Метод возвращает фамилию человека
sub getFamily {
    return shift->[1];
}

# Метод возвращает возраст человека
sub getAge {
    return shift->[2];
}

# Метод меняет имя человека
sub setName {
    my $self = shift;
    $self->[0] = shift if scalar @_;
}

# Метод меняет фамилию человека
sub setFamily {
    my $self = shift;
    $self->[1] = shift if scalar @_;
}

# Метод меняет возраст человека
sub setAge {
    my $self = shift;
    $self->[2] = shift if scalar(@_) && $_[0] > 0;
}

################################################################################
# Имитируем перегруженный метод. Если метод получает число, оно прибавляется   #
# к возрасту, если же метод был вызван без параметров, то добавляем к возрасту #
# единицу.                                                                     #
################################################################################
sub addAge {
    my $self = shift;
    my $add  = (scalar(@_) && ($_[0] =~ /^\d+$/) && ($_[0] > 0)) ? shift : 1;
    $self->[2] += $add;
}

1;
 
а вот программа, которая его использует:
Код

#!/usr/bin/perl -w
use strict;
use Person;

# Создаём массив объектов Person
my @people = (
    new Person("Вася", "Пупкин", 16),
    new Person("Коля", "Герасимов", 12),
    new Person("Валя", "Брусникина", 20)
);

# Пройдём по всему массиву и покажем информацию о каждом человеке
foreach my $person (@people) {
        print "Имя: " . $person->getName() . "\n";
        print "Фамилия: " . $person->getFamily() . "\n";
        print "Возраст: " . $person->getAge() . "\n\n";
}

# Следующая строка, просто разделитель
print "=" x 80, "\n";

################################################################################
# Теперь можно добавим каждому по одному году используюя метод addAge() без    #
# параметров. И снова покажем весь список.                                     #
################################################################################
for (my $i=0; $i < scalar(@people); $i++) {
     # Я намеренно использовал цикл for с переменной - счётчиком,
     # так, для разнообразия.
     $people[$i]->addAge();
}

################################################################################
# Покажем заново всех людей из нашего массива, так как нам массив дальше не    #
# понадобится, то обнуляем массив и попутно выводим информацию окаждом клиете  #
################################################################################
while (my $person = shift @people) {
       print "Имя: " . $person->getName() . "\n";
       print "Фамилия: " . $person->getFamily() . "\n";
       print "Возраст: " . $person->getAge() . "\n\n";
}

Кстати, можно так же заюзать псевдо-хеш, хотя они сейчас помечены как depricated, но в Perl можно реализовать что-то похожее на псевдо-хеш вручную, а можно так же и не вручную, например заюзав прагму компилятора fields  smile 

Цитата(Bulat @  2.10.2007,  06:17 Найти цитируемый пост)
М-дя, и в догонку очень важный вопрос о деструкторах... В яве-то их ручками писать не надо, а как насчет перла ?? 

В Perl сборка мусора происходит тоже автоматически, примерно так же, как и в Java, потому деструкторы нужно юзать, как сказал nitr, только в исключительных случаях.

Это сообщение отредактировал(а) korob2001 - 2.10.2007, 20:09


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


Эксперт
****


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

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



Кстати, ты говорил, что знаком с Java. Вот я тут как-то приводил пример того, как можно создавать классы Java на лету, прямо из Perl программы, а после этого создавать объекты в Perl программе и работать с ними, как с родными Perl объектами. Это работает примерно так же, как встроенный код Assembler'a в программу C++.

Вот здесь можешь посмотреть этот пример.

Кстати, таким же макаром, можно встраивать в Perl программу и код на C++, Assembler, Basic, да и многих других языков и не только языков. Вобщем если будет интересно, то поищи модули на cpan.org, по ключевому слову "Inline". Если ты под виндой, то можешь просто набрать в командной строке, такую команду:

C:\>ppm s Inline

Получишь список модулей, для встраивания кода других языков в Perl программу. Что бы установить модуль дай команду:

C:\>ppm i Inline-Java

Или другое имя модуля, вместо Inline-Java.





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


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



korob2001, ну инкапсуляция перемнных в классе-контейнере, вообще очень важна, так как если в ходе работы программы у нас создается не один экземпляр класса, то потом при попытке получить доступ, может вообще такая путаница произойти.... Вообщем как-то было у меня один раз в яве, после чего даже не стал разбиратся, тут это для меня как бы аксиома

В целом огромное пасиба, за очень содержательные ответы... А ссылки на досуге обязательно почитаю, хотя в моей текущей конторе мы пишем исключительно на перле.. Да и раньше кода я комбинировал яву с перлом, то это были отдельные программы одной системы, как правило перл использовал за их регулярки... Если же внутри кода создавать, то я так понимаю, нужно будет устанавливать и виртуальную ява-машину, сейчас, я думаю мне этого никто не позволит сделать, в новой конторе я еще не набрал такого "веса"  smile 

cerf_machine, тоже большой сенкс smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
cerf_machine
Дата 4.10.2007, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата

Но, Perl позволяет сделать закрытость ещё более надёжную, чем другие языки программирования, разумеется, если это нужно.

Ух, тыsmile

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

korob2001, спасибо.
Bulat, не за что;)
PM MAIL ICQ   Вверх
Bulat
Дата 5.10.2007, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



К сожалению пока углубится особенно в ООП на перле нет времени...

Появился такой вопрос...

При стандартном сеттере, если передаешь в качестве параметра не саму переменную, допустим $name = "Александр", а

setName((shortName($name)));

т.е., процедура shortName делает какие-то модификации с самой переменной...

??


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
cerf_machine
Дата 5.10.2007, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Не понял вопрос.

Код

setName( shortName( $name ) );


setName получит $_[0] => return-значение shortName.
PM MAIL ICQ   Вверх
Bulat
Дата 5.10.2007, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



cerf_machine

вопрос ты как раз понял и ответил на него smile

Я лишь хотел убедится, что реально метод получит значение возвращаемое процедурой smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
korob2001
Дата 5.10.2007, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Ответ уже дали, но всё же решил привести ещё один пример, так на всякий случай  smile :
Код

#!/usr/bin/perl -w
use strict;
use Person;   # Наш класс

# Если программа не получила параметр, покажем информацию, как правильно
# запустить её с терминала.
die "\nPlease start this programm with one parameter - your name.\n" .
    "Forexample so:\nC:\\>perl $0 aNtOn\n" unless @ARGV;

# Создаём объект класса Person
my $person = new Person();

# Установим имя из полученное из командной строки коммандной строки
$person->setName( ucfirst( lc( shift )));

# Выводим имя на STDOUT
print "\nYour name is: @{[$person->getName()]}\n";

Теперь осталось запустить программу из командной строки и передать ей своёимя в качестве параметра. Причём, что бы налядно увидеть работу программы, имя должно быть в беспорядочном регистре, например так: dEnNiS. Если программа была запушена правильно, то регистр будет исправлен.

Нас интересует строка:
Код

$person->setName( ucfirst( lc( shift )));

Сначала передаём параметр функции lc(), она преобразует строку в нежний регистр, т.е. она возвращает строку "dennis"  и тут же передаёт её дальше, функции ucfirst(), которая поднимает первый символ строки в верхний регистр и возращает результат "Dennis" и наконец предаёт отредактированное имя методу $person->setName().
Т.е. сначала выполняется самая внутренняя функция, это аналогично применению скобок для изменения приоритета арифметических операций.

Тоже самое можно делать и с методами, добавим в код ещё две строки, теперь он выглядит так:
Код

#!/usr/bin/perl -w
use strict;
use Person;   # Наш класс

# Если программа не получила параметр, покажем информацию, как правильно
# запустить её с терминала.
die "\nPlease start this programm with one parameter - your name.\n" .
    "Forexample so:\nC:\\>perl $0 aNtOn\n" unless @ARGV;

# Создаём объект класса Person
my $person = new Person();

# Установим имя из полученное из командной строки коммандной строки
$person->setName( ucfirst( lc( shift )));

# Выводим имя на STDOUT
print "\nYour name is: @{[$person->getName()]}\n";

# Преобразуем уже установленное имя в верхний регистр
$person->setName( uc( $person->getName() ) );

# Выводим имя на STDOUT
print "\nYour name is: @{[$person->getName()]}\n";

В строке:
Код

$person->setName( uc( $person->getName() ) );

сначала выполняется метод $person->getName(), он возвращает текущее имя "Dennis", это имя передаётся функции uc(), которая переводит верхний регистр всю строку "DENNIS" и в конце устанавливаем уже проеобразованное имя методом $person->setName(). 

Это сообщение отредактировал(а) korob2001 - 5.10.2007, 17:06


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


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



В целом, тема очень широкая, и появились еще дополнительные вопросы... Вообще конечно, кое-что уже было разъяснено ;) однако я сам не с того конца сформулировал вопрос, поэтому и не получил все ответы на него...

В целом получится может даже убить два зайца...

Изначально был очень хороший, но все же тривиальный пример... А меня сейчас интересует нечто более глубже... В данном примере, все поля класса - хеши, у класса есть свои методы и т.п. Все это хорошо, но если нам нужно что-то более сложноструктурированное, чтоб допустим этот класс, являлся лишь полем какого-то другого класса... И при этом из нового класса, доступ ко всем методам класса текущего, получается что-то типа наследования... Если не представится сложным, хотелось также затронуть момент переопределения метода, и для разнообразия побольше функциональных действий в самом конструкторе...

P.S. В дополнение, также пока не совсем понял как лучше работать с директориями(пакетами), куда можно объеденить несколько классов, попытаюсь изобразить более визуально

./myScript.pl - <корневой скрипт>
./myClasses/... - пакет, где находятся классы, допустим
    ./myClasses/classesForDB/...
    ./myClasses/classesForFiles/...
    ./myInterfaces/....
./myUtils/... - также содержатся какие-то классы
./myModules/... - просто модули
./files/... - пакет просто для каких-то конфигов, xml-файлов, или еще чего-нить
...

Для знатока явы, я думаю понятно, что я хотел спросить про пакеты и подпакеты smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
vadiml
Дата 18.11.2007, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 5
Всего: 7



> чтоб допустим этот класс, являлся лишь полем какого-то другого класса

создаешь переменную в классе и этой переменной присваиваешь класс, т.к. класс в перле это всего лишь blessed ссылка (или array, ...)

> хотелось также затронуть момент переопределения метода, 

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

другое дело если надо в классе переопределить встроенный в перл метод -- в начале класса надо объявить эту функцию, например переопределение split:
use subs qw(split);
а уже ниже её описать.
экспортировать такую функцию не советую, путь живёт в пространстве имен только этого класса

> побольше функциональных действий в самом конструкторе...

в конструкторе можно делать что угодно, это самая обычная функция, которую и обозвать можно как угодно, например в Tk принято конструктору давать имя класса, хотя наиболее частый вариант -- это new

> как лучше работать с директориями(пакетами), куда можно объеденить несколько классов

создать для них каталог, например QQQ, и потом подключать их как
use QQQ::модуль1;
use QQQ::модуль2;

но и названия пакетов внутри тоже должны быть приведены к этому виду:
package QQQ::пакет1;
use 5.008;
use strict;

use QQQ::модуль2;
...

ЗЫ посмотри любой каталог, где лежат модули перла

PM MAIL Jabber   Вверх
Bulat
Дата 20.11.2007, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



Цитата(vadiml @  18.11.2007,  18:18 Найти цитируемый пост)
создать для них каталог, например QQQ, и потом подключать их как
use QQQ::модуль1;
use QQQ::модуль2;

но и названия пакетов внутри тоже должны быть приведены к этому виду:
package QQQ::пакет1;
use 5.008;
use strict;

use QQQ::модуль2;


Все же не совсем понял, а именно

use QQQ::модуль1;
package QQQ::пакет1;
use QQQ::модуль2;

тривиальный пример

есть два модуля: util.pm и work.pm, что и где должно прописатся чтобы можно было работать при структуре

./mainScript.pl
./modules/util.pm
./modules/work.pm

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

Пример конечно не плохой, но уж слишком "на пальцах" smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
Bulat
Дата 20.11.2007, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



Хм...

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

модуль

Код

#!/usr/bin/perl

package modules::printDatas;

use strict;

BEGIN {

    use Exporter ();

    our @ISA = 'Exporter';
    our @EXPORT;

    push @EXPORT , '&PrintHeader';
    push @EXPORT , '&PrintFooter';
    push @EXPORT , '&PrintMainLinks';
}

sub PrintHeader {
    print (qq{
        <html>
            <head>
                <title>File Uploader</title>
                <meta http-equiv="content-type" content="text/html; charset=utf-8">
            </head>
            <body>
    });
}

sub PrintMainLinks {
    print (qq{
        <br>
            <div align = "right">
                <h4>
                    <a href = "/servers/">Show servers list</a>
                </h4>
            </div>
        <br>
    });
}

sub PrintFooter {
    print (qq{
            </body>
        </html>
    });
}

sub PrintServersList {
}

1;

END { };


соотв в самом скрипте достаточно подключить его use modules::printDatas, а для вызова процедуры достаточно PrintHeader допустим, но здесь у меня возник еще один вопрос. В модуле я ручками прописываю     push @EXPORT , '&PrintHeader';, но если уже есть хотелось бы, чтоб это выполнялось для всех процедур, которые есть в модуле... Конечно можно и ручками придумать нечто подобное, но если велосипед изобрели до меня smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
vadiml
Дата 23.11.2007, 23:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 5
Всего: 7



Для экспорта должен быть резон
Иногда гораздо читабельне вызывать функции по полному имени:
modules::printDatas::PrintHeader();
или для чего-то с зависимым содержанием создали класс, а потом вызывали через его указатель функции:
my $pd = printDatas::new();
$pd->PrintHeader();

А если Вам хочется заняться экспортом, то надо заметить, что экспортироваться могут не только функции, но и любые переменные, массивы, хеши.
а 
our @EXPORT;
push @EXPORT , '&PrintHeader';
... # куча push
проще описать как 
our @EXPORT = qw(PrintHeader PrintFooter PrintMainLinks);
не забывайте про списковый контекст, это часто очень удобный способ передачи данных

PS вообще плохой пример с названием modules, желательно что-то осмысленное. В лучше бы Вы подключили каталог modules в переменную просмотра путей для поиска модулей:
use lib qw(ваш_путь/modules ещё_один_путь_к_другой_группе_модулей);
use printDatas;
...
printDatas::PrintHeader();

PPS пустой блок END { } не имеет смысла, как и BEGIN стоящий в самом начале файла -- код в нем и так выполнится первым.
Главное чтоб Вы модули подключали через use, а не require, при первом способе компиляция выполняется при старте программы, при втором -- при обращении к ней.
PM MAIL Jabber   Вверх
Bulat
Дата 25.11.2007, 22:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



Цитата(vadiml @  23.11.2007,  23:50 Найти цитируемый пост)
Для экспорта должен быть резон
Иногда гораздо читабельне вызывать функции по полному имени:

Резон-то есть... Методы(процедуры) вызываются в основном скрипте, это все ж не просто классы экземпляры данных smile


Цитата(vadiml @  23.11.2007,  23:50 Найти цитируемый пост)
проще описать как 
our @EXPORT = qw(PrintHeader PrintFooter PrintMainLinks);


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


Цитата(vadiml @  23.11.2007,  23:50 Найти цитируемый пост)
PPS пустой блок END { } не имеет смысла, как и BEGIN стоящий в самом начале файла -- код в нем и так выполнится первым.


скока пишу, столько встречаюсь, что не поставленные где-то скобки(потому как сейчас они не имеют смысла) и т.п. частенько плачевно заканчиваются, лучше все же сначала закончить написание всего кода, а уже потом решать что нужно, а что нет ;)



--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
Bulat
Дата 15.9.2009, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



некромантирую свою старую тему. smile

Хотелось бы узнать делал кто-нить, если - да, то мож пример какой по переопределению методов, то бишь функций.. Полная аналогия с тем, что в ООП называется переопределение. smile

И даже для большего страха  smile переопределение функций не собственно-написных модулей или классов, а чего-нить из более стандартного.. Например какая-нить функция из того же DBI или CGI..

Ес-но, сама суть в том, чтобы организовать хак, при котором определенная функция переопределяется и начинает работать по иному алгоритму нежели стандартная smile

P.S. Интересует именно переопределение, а не альтернативные реализации хака ))


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
gcc
Дата 15.9.2009, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Агент алкомафии
****


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

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



SUPER псевдо-класс?

Код

use base qw/CGI/;        

sub header { 
my $self = shift;
unless ($myCGI::__HEADER_METHOD_WAS_RUNED_MORE_THAT_ONCE) {
  $myCGI::__HEADER_METHOD_WAS_RUNED_MORE_THAT_ONCE = 1;   # возведем ключ в пакете
  #
  # Метод супер-класса - старый header - нужно вызвать - кто-то ведь должен работать!
  # А в принципе его работа нас устраивает!
  #
  return $self->SUPER::header(@_);       # про параметры - не забываем!
  #
} else {
  
  # caller()  
  warn "Calling heaвer again... Strange situation! \n";
  

}





Это сообщение отредактировал(а) gcc - 15.9.2009, 12:10
PM WWW ICQ Skype GTalk Jabber   Вверх
sir_nuf_nuf
Дата 15.9.2009, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



делали.. для какого то мелкого модуля протокола STOMP..
Но если не используется OOP - это довольно шаткое решени.

Заменить процедуру в любом модуле легко
Код

package B;
*A::foo = sub {print "this is new foo\n";}
 

Однако, если эта процедуру кто ли-бо импортировал до момента подмены - у них останется старая. 
В этом весь трабл.
Код

package C;
use A qw(foo);

package B;
*A::foo = sub {print "this is new foo\n";}

package C;
foo(); # ooops, still old foo()


Поэтому если вы хотите такое провернуть, то нужно подменять процедуру в самом начале
Код

package B;
BEGIN {*A::foo = sub {print "this is new foo\n";}}
package C;
use A qw(foo);
foo(); #yeah! new foo is so new!



--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
Bulat
Дата 15.9.2009, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



Цитата(sir_nuf_nuf @  15.9.2009,  12:51 Найти цитируемый пост)
Однако, если эта процедуру кто ли-бо импортировал до момента подмены - у них останется старая.


Вот на этом моменте я тоже призадумался

Цитата(sir_nuf_nuf @  15.9.2009,  12:51 Найти цитируемый пост)

Поэтому если вы хотите такое провернуть, то нужно подменять процедуру в самом начале


В том-то и вся проблема, что при такой реализации - все будет выглядеть еще некрасивее. smile

gcc, не натыкается-ли твой способ на эти же грабли?? smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
gcc
Дата 15.9.2009, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Агент алкомафии
****


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

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



для множественного наследования есть давно: use NEXT; http://search.cpan.org/~flora/NEXT-0.64/lib/NEXT.pm

и много разных дополнений написанных на Си  use Class::C3; http://search.cpan.org/~blblack/Catalyst-P...st/Plugin/C3.pm
http://search.cpan.org/search?query=mro&mode=all

в каталисте в новой версии используется: 
Class::C3::Adopt::NEXT http://search.cpan.org/~flora/Class-C3-Ado...3/Adopt/NEXT.pm в отладке выводиться сообщение что нужно перейти на этот модуль

(проблем с переопределение в данном случае по-моиму не будет)
Код

use Class::C3::Adopt::NEXT;

sub new {  # наследуем конструктор
    my ( $self, $c ) = @_;
        $self = $self->next::method(@_);
}



Код

  *Foo::foo = sub { (shift)->next::method(@_) };


в какой-то старой книге (Кристенсен 2 или 3 издание, я книгу сейчас не смог открыть компе) было написано что можно как-то обойти это если использовать множественное наследование с SUPER...





Это сообщение отредактировал(а) gcc - 15.9.2009, 19:12
PM WWW ICQ Skype GTalk Jabber   Вверх
sir_nuf_nuf
Дата 15.9.2009, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Bulat @  15.9.2009,  16:37 Найти цитируемый пост)
В том-то и вся проблема, что при такой реализации - все будет выглядеть еще некрасивее

Подменять чужие функции - вообще некрасиво.
Другое дело как это сделать менее убого..
Ну создайте отдельный модуль типа .. Startup, в котором весь этот кошмар и изложите.
А далее - либо первой строчкой своего скрипта его подгружайте, либо как startup.pl при старте mod_perl


--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
gcc
Дата 15.9.2009, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Агент алкомафии
****


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

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



sir_nuf_nuf, а NEXT тут разве не подходит? его автор сделал как раз для множественного наследования...
PM WWW ICQ Skype GTalk Jabber   Вверх
sir_nuf_nuf
Дата 16.9.2009, 08:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



gcc, нет. он подходит только если наследование (т.е. ООП) вообще имеет место.
Мы же говорим про импорт обычных процедур. не методов объектов


--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
Bulat
Дата 16.9.2009, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



Цитата(gcc @  15.9.2009,  23:43 Найти цитируемый пост)
sir_nuf_nuf, а NEXT тут разве не подходит? его автор сделал как раз для множественного наследования... 


Действительно, это важный момент, сохранять целостность семантики кода... Тот кто после меня посмотрит мой код должен понимать не только как, но и что в нем происходит, а когда налеплено где-то процедурное, где-то ООП - это тоже не красиво... smile


Цитата(sir_nuf_nuf @  15.9.2009,  23:19 Найти цитируемый пост)
Ну создайте отдельный модуль типа .. Startup, в котором весь этот кошмар и изложите.
А далее - либо первой строчкой своего скрипта его подгружайте, либо как startup.pl при старте mod_perl 


Вариант.. smile может быть..


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
gcc
Дата 16.9.2009, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Агент алкомафии
****


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

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



Bulat, а в Java множественного наследования вроде бы нету и не будет...

PM WWW ICQ Skype GTalk Jabber   Вверх
Bulat
Дата 16.9.2009, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



Цитата(gcc @  16.9.2009,  14:07 Найти цитируемый пост)
Bulat, а в Java множественного наследования вроде бы нету и не будет...


Java - это уже сам по себе объекто-ориентированный и ссылочный язык. Там много устроено по иному нежели в перл... И переопределение происходит на уровне дочернего класса... Кроме того и перегрузка методов еще есть...

Пафос перла-то в том, что нет необходимости писать огромное количество кода, когда можно обойтись десятью строчками. smile

А в Java как такого множественного наследования нет, но есть интерфейсы ;) Хотя по мне это одно и то же... Ну мож за всю жизнь пару раз все же придется залезть так "глубоко", чтоб почувствовать и в этом разницу smile


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


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

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


 




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


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

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