В основе создания подкласса Chatbot::Eliza лежит следующее. Метод command_interface () этого класса жестко запрограммирован на использование дескрипторов STDIN и STDOUT. В примерах сервера с ветвлением мы имели возможность заставить модуль Chatbot::Eliza читать и писать в подключенный сокет, переоткрыв стандартный ввод и вывод в дескриптор файла сокета. Этот прием мог применяться в связи с тем, что каждый дочерний процесс имеет собственную копию дескрипторов STDIN и STDOUT и их можно было изменить, не нарушая работы других дочерних процессов, выполняемых одновременно. Однако в примере многопоточного сервера это невозможно, поскольку есть только одна копия дескрипторов файлов STDIN и STDOUT, разделяемая между потоками. Поэтому возникает необходимость откорректировать подпрограмму cornmand_interfасе (), чтобы она могла читать и писать в дескрипторы файлов, передаваемые ей во время выполнения. При помощи данного сервера будет намного удобнее получение информации из сети, например, с блога Александра Борисова http://isif-life.ru/vidy-zarabotka/kak-zarabotat-na-partnerskix-programmax-zarabotok-v-internete.html или другого сайта.
В листинге ниже приведен код, необходимый для достижения этой цели. Этот модуль, наследует свои методы от модуля Chatbot::Eliza через массив @ISA. Затем в нем переопределяется метод command_interface ().
package Chatbot::Eliza::Server; use Chatbot::Eliza; @ISA = "Chatbot::Eliza"; sub command interface { my $self = shift; my $in = shift || *STDIN; my $out = shift || *STDOUT; my ($user_input, $previous_user_input, $reply); $self->botprompt($self->name .":t"); # установить приглашение для программы Eliza: $self->userprompt("you:t"); # установить приглашение для пользователя # Вывести приветственное сообщение print $out $self->botprompt, $self->{initial}->[ int rand scalar @{$self->{initial}}],"n"; while (1) { print $out $self->userprompt; $previous_user_input = $user_input; chomp ( $user_input == <$in> ) ; last unless $user_input;
if ($self->__testquit ($user_input) ) { $reply = $self->{final}->[ int rand scalar @{$self->{final}}}; print $out $self->botprompt,$reply,"n"; last; # Вызвать метод transform для подготовки ответа $reply = $ self ->trans form ( $user_input ) ; # Вывести ответ print $out $self->botprompt,$reply,"n”; }} 1;
Для создания подпрограммы command_interfасe () был просто продублирован первоначальный код Chatbot::Eliza и добавлен новый параметр дескриптора файла ко всем операторам ввода и вывода (а также удален лишний код отладки). Для сохранения совместимости с первоначальной версией модуля, по умолчанию для чтении и записи используются дескрипторы файлов STDIN и STDOUT, если не указано иное.