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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Импорт методов и подпрограмм одновременно 
V
    Опции темы
Danissimo
Дата 13.12.2006, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Пусть объявлен пакет, в котором difinize не является методом класса, а просто подпрограммой:
Код

package DAO;

use warnings;
use diagnostics;
use strict;

use Exporter;
our @EXPORT;
@EXPORT = qw { &definize };

sub definize {
    if (!defined wantarray) {
        foreach (@_) {
            $_ = 'undef' unless defined $_;
        }
        return;
    }
    if (wantarray) {
        my @r = @_;
        foreach (@r) {
            $_ = 'undef' unless defined $_;
        }
        return @r;
    }
    return defined $_[0] ? $_[0] : 'undef';
}

sub new {
    ...
}

Пусть объявлен подкласс:
Код

package MACHINE_DAO;
use base 'DAO';
sub myMethod {
    my $self = shift;
    ...
    my $r = ...;
    print 'Result: ' . definize $r . "\n";
    ...
}

Вот к чему это приводит:
Код

Can't call method "definize" on an undefined value at MACHINE_DAO.pm line 33 (#1)
    (F) You used the syntax of a method call, but the slot filled by the
    object reference or package name contains an undefined value.  Something
    like this will reproduce the error:

        $BADREF = undef;
        process $BADREF 1,2,3;
        $BADREF->process(1,2,3);

Uncaught exception from user code:
        Can't call method "definize" on an undefined value at MACHINE_DAO.pm line 33.
        MACHINE_DAO::getCanonicalModelId('MACHINE_DAO=HASH(0x34fbbc)', 'Unknown', 2) called at test_DAO.pl line 13

Хочется вызывать definize, не указывая пакет: DAO::definize. Более того, definize не является методом класса. Это просто вспомогательная подпрограмма.

Как мне достичь желаемого? Да, и поругайте заодно метод definize. (Может эту ветку лучше было создать в "CGI программировании"...)

Это сообщение отредактировал(а) Danissimo - 13.12.2006, 16:09
PM MAIL   Вверх
f00Gass
Дата 13.12.2006, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



...
use base 'DAO';
...
замени на 
...
use DAO;
push @ISA, qw (DAO);
...

Дело в том что "use base 'DAO';" почти эквиваленто

BEGIN
{
        require DAO;
        push @ISA, qw(DAO);
}

Это сообщение отредактировал(а) f00Gass - 13.12.2006, 16:26
PM MAIL   Вверх
Danissimo
Дата 13.12.2006, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Вот как я написал:
Код

package MACHINE_DAO;

use strict;
use warnings;
use diagnostics;

use DAO;
our @ISA;
@ISA = ('DAO');

sub getCanonicalModelId {
    my $self = shift;
    ...
    my $r = ...;
    print 'getCanonicalModelId = success: [' . definize $r . "]\n";
    ...
}

1;

То же самое.
PM MAIL   Вверх
f00Gass
Дата 13.12.2006, 16:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



А эту функцию экспортировал из DАО?

И, вообще, судя по тексту ошибки, ты пытаешься вызвать свою лабуду как метод!

Can't call method "definize" on an undefined value at MACHINE_DAO.pm line 33.

Это сообщение отредактировал(а) f00Gass - 13.12.2006, 16:58
PM MAIL   Вверх
Danissimo
Дата 13.12.2006, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Да, экспортирую.

Цитата

И, вообще, судя по тексту ошибки, ты пытаешься вызвать свою лабуду как метод!

Круто! А я вот даже и не ведаю. Я вот дурею от того, что, как показывает практика (ну, например, вот вы, гуру, по тексту программы не можете понять, вызов метода или нет -- только по тексту ошибки), в перле на каждой строчке ожидает подвох. И не один =)

Все-таки языки с четкой грамматикой и этапом компиляции рулят =))

PM MAIL   Вверх
f00Gass
Дата 13.12.2006, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Ты ту строку кода показваешь? smile
То что тама вызвывается подпрограмма, а не метод, и так видно... 

Добавь, наконец, Exporter в @ISA в твоём DAO!

З.Ы.:Короче, почитай внимательнее доки, и тогда подводных камней не будет, Даниссимо smile

Это сообщение отредактировал(а) f00Gass - 13.12.2006, 18:07
PM MAIL   Вверх
Danissimo
Дата 13.12.2006, 20:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Все понятно. Я вот читаю втою фразу: "И, вообще, судя по тексту ошибки, ты пытаешься вызвать свою лабуду как метод!" Смотрим следующий пост: "То что тама вызвывается подпрограмма, а не метод, и так видно..." Какие аасоциации возникают? Тока, чур, не думать.

У меня большая просьба. Я не мальчик, который лабу пишет или 3 месяца программированием дегьги зарабатывает. Думаю, не ошибусь, если скажу, что многим бы не помешало поучиться тому, чему я научился. Так вот просьба следующая: если не можете ответить на вопрос, просто не отвечайте на него. Пожалуйств. Выглядит дешево.

Я ведь простых вещей в последнее время не спрашиваю.
PM MAIL   Вверх
f00Gass
Дата 13.12.2006, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Не вижу ничего сложного в твоём вопросе... Ты просто пытаешься вызвать подпрограмму из пакета, при этом не зная как строится пакет и как экспорировать имена... Это ОСНОВЫ! Я указал на твои ошибки. Читай внимательней..

Это сообщение отредактировал(а) f00Gass - 13.12.2006, 20:43
PM MAIL   Вверх
nitr
Дата 13.12.2006, 20:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Я как-то встречал при регистрации на каком-то форуме был пункт:
"Обязуюсь читать маны, доки и Факи перед тем как задать вопрос!" smile
тут похож иногда тоже надо.

Danissimo, я думаю ты привык к разжёванным ответам korob'а smile

з.ы.:
Danissimo, чтобы ещё меньше задавать вопросы, купи КукБук, согласен ей уже переиздание необходимо, но! помогает. В месте с ней perldoc. Ну и книжку от Ларри ;)
Тут на форуме были ссылки на электрон. версии разных книг. А то если переписывать множество perldoc в пережёванном виде... форума не хватит

Это сообщение отредактировал(а) nitr - 13.12.2006, 20:53


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


Эксперт
****


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

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



1. От Exporter нужно унаследовать, а не просто подключить его.
2. Экспортируемые подпрограммы пишутся в массив без знака амперсанда.

Вобщем попробуй выполнить такой код:
Модуль Parent.pm
Код

package Parent;

require Exporter;
our @ISA = ("Exporter");

@EXPORT = (getHello);

sub getHello {
    my $self = shift if ref($_[0]);
    my $name = shift || "Anonim";
    return __PACKAGE__ . " - Hello, $name!";
}

1;

Класс Child.pm
Код

package Child;

use Parent;

sub new {
    return bless({},ref($_[0])||$_[0]);
}

sub myMethod {
    my $self = shift if ref($_[0]);
    my $name = shift;
    return __PACKAGE__ . " - " . getHello($name);
}

1;

Программа для теста test.pl
Код

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

my $child = new Child();

print $child->myMethod("Denis")."\n";
print Child::getHello("Denis") . "\n";
print $child->getHello("Denis") . "\n";

Здесь показаны разные вызовы попдпрограммы которая экспортируется в пространство имён пакета Child.
Отсюда вывод:
Цитата

Хочется вызывать definize, не указывая пакет: DAO::definize. Более того, definize не является методом класса. Это просто вспомогательная подпрограмма.

Она экспортируется, но она доступна, так как нам доступно имя пакета, куда эта подпрограмма была экспортирована.
Насколько я понял, ты пытаешься найти в Perl аналог private из Java.  smile  Если да, то не найдёшь. Но отчаиваться не стоит, на самом деле в Perl можно сделать куда большую закрытость, чем ты себе её представляешь. Это аналог закрытого метода в Java:
Класс: PrivateTest.pm
Код

package PrivateTest;

# Коструктор класса
sub new { return bless({},ref($_[0])||$_[0]); };


# Зыкрытый метод, вспомогательный. Из другого пакета не получится вызвать
my $sum_row = sub {
   my $self = shift;
   my $row  = shift || [];
   my $sum  = 0;
   $sum += $_ for (@$row);
   return $sum;
};

# Метод получает массив массивов и подсчитывает сумму всех елементов массива
# Для подсчёта каждого ряда использует закрытый метод.
sub sumArrayOfArray {
    my $self = shift;
    my @array = @_;
    my $sum = 0;
    $sum += $sum_row->($self,$_) for (@array);
    return $sum;
}

1;

Вот код, который подсчитывает сумму всех чисел из массива массивов.
Программа test.pl
Код

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

my $prv = new PrivateTest();

# Объявляем и инициализируем массив массивов
my @arr = (
   [1,2,3],
   [1,2,3],
   [1,2,3],
);

# Подсчитываем и выводим сумму всех елементов
print $prv->sumArrayOfArray(@arr);

Попробуй как-нить вызвать закрытый метод.
Мало того, можно даже закрыть его (метод) от самого себя. ;))))))) Скажем так:
Класс PrivateTest.pm
Код

package PrivateTest2;

sub new {return bless({},ref($_[0])||$_[0])};

################################################################################
#Все методы которые находятся здесь не имеют доступа к закрытому методу $sum_row
################################################################################

# Создаём лексическую область видимости
{
    # Зыкрытый метод, вспомогательный. Вне лексической области не получится вызвать
    my $sum_row = sub {
        my $self = shift;
        my $row  = shift || [];
        my $sum  = 0;
        $sum += $_ for (@$row);
        return $sum;
    };

    # Метод получает массив массивов и подсчитывает сумму всех елементов массива
    # Для подсчёта каждого ряда использует закрытый метод. Он единственный который
    # имеет доступ к закрытому методу.
    sub sumArrayOfArray {
        my $self = shift;
        my @array = @_;
        my $sum = 0;
        $sum += $sum_row->($self,$_) for (@array);
        return $sum;
    }
} # Конец лексической области

################################################################################
#Все методы которые находятся здесь не имеют доступа к закрытому методу $sum_row
################################################################################

1;

Т.е. к закрытому методу имеют доступ только методы, который находятся с ним в одной лексической области. Для теста можешь попробовать вынести метод sumArrayOfArray() за пределы лексической области и зупусти пример снова.
Вопрос лишь в том, нужно ли это?

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


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


Бывалый
*


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

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



Цитата(nitr @ 13.12.2006,  20:46)
Я как-то встречал при регистрации на каком-то форуме был пункт:
"Обязуюсь читать маны, доки и Факи перед тем как задать вопрос!" smile
тут похож иногда тоже надо.

Danissimo, я думаю ты привык к разжёванным ответам korob'а smile

з.ы.:
Danissimo, чтобы ещё меньше задавать вопросы, купи КукБук, согласен ей уже переиздание необходимо, но! помогает. В месте с ней perldoc. Ну и книжку от Ларри ;)
Тут на форуме были ссылки на электрон. версии разных книг. А то если переписывать множество perldoc в пережёванном виде... форума не хватит


Смотрите, как я это вижу. Да, было бы не плохо прочиать несколько книжек, пописать пару лет на перле и т. д. Не могу я себе позволить такую роскошь. А вы это уже сделали, как я ожидаю. Вы прочли, вы пописали. Вы знаете best practices, подводные камни, лучшие решения. Вобщем все то, что приходит с опытом. Я этого ничего не знаю. Именно этот опыт я и преобретаю. Да, я привык рассматривать несколько вариантов решения, выбирать лучший (и не редко единственный).

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

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

Я понятно объясняю?
PM MAIL   Вверх
Danissimo
Дата 14.12.2006, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Нет, не аналог private. А аналог вот чего:
Код

class DAO {
    // Для вызова этого метода [color=red]не нужен экземпляр класса[/color]
    // Вызывать этот метод могут [color=red]все[/color]
    public static String definize(String s) {
        return s == null ? "null" : s;
    }

    // Вызвать метод можно только, [color=red]имея экземпляр[/color]
    // Вызвать этот метод могут только наследники
    protected Connection getConn() {
        ...
    }

    // Этот метод могут вызывать только наследники и только используя
    // экземпляр класса.
    protected final void debug(String msg) {
        ...
    }
}

class Data {
    public String col1, col2, col3;

    public String toString() {
        // Вызывая DAO.definize(), явно указывается класс, в котром вызывается метод,
        // так как Data не является наследником класса DAO, следовательно definize()
        // не попадает в пространство имен Data.
        //
        // В то же время экземпляр класса DAO для вызова definize() не требуется.
        return "<" +
                DAO.definize(col1) + ", " +
                DAO.definize(col2) + ", " +
                DAO.definize(col3) + ">";
    }
}

class MyDAO extends DAO {
    public Data getData() {
        Statement stmt = getConn().prepareStatement(...);
        Data data = new Data(stmt.executeQuery());

        // Вызывая definize(), класс не указывается, так как MyDAO является наследником
        // класса DAO, следовательно definize() попадает в пространство имен MyDAO.
        String msg = "Selected: <" +
                definize(data.col1) + ", " +
                definize(data.col2) + ", " +
                definize(data.col3) + ">\n";
        debug(msg); // Обратите внимание, здесь я вызываю метод [color=red]экземпляра[/color] класса
        return data;
    }
}


Добавлено @ 17:11 
Ага, значит в пакете Parent ты явно говоришь @EXPORT=(getHello), добиваясь тем самым того, что метод getHello() попадает в пространство имен Child. Сам метод getHello() может работать и как метод класса, и как отдельно стоящая подпрограмма. В методе Child::myMethod() ты вызываешь getHello():
  • как подпрограмму, а не как метод класса;
  • явно не указывая пакет, в котором объявлена подпрограмма;
  • из метода класса, а не из просто подпрограммы.
Тем самым ты точно смоделировал ситуацию (на самом деле, я восхищен). Тогда, интересно, почему у меня не работало. Я ведь тоже также объявлял подпрограмму, вносил ее в @EXPORT, вызывал, не указывая пакета, вызывал из метода класса.

Правильно я думаю, что мой вариант не работал потому, что я не указывал скобки и потому, что я не наследовался от Exporter, а всего лишь use его?
PM MAIL   Вверх
Danissimo
Дата 15.12.2006, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Тема, вроде бы, себя исчерпала. Рядом (http://forum.vingrad.ru/topic-127038.html) обсуждается примерно то же самое.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


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

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


 




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


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

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