Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Languages
 С
 GNU С Library 
 Qt 
 STL 
 Threads 
 C++ 
 Samples 
 stanford.edu 
 ANSI C
 Libs
 LD
 Socket
 Pusher
 Pipes
 Encryption
 Plugin
 Inter-Process
 Errors
 Deep C Secrets
 C + UNIX
 Linked Lists / Trees
 Asm
 Perl
 Python
 Shell
 Erlang
 Go
 Rust
 Алгоритмы
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 MINIX...3057 
 Solaris...2933 
 LD...2906 
 Linux Kernel 2.6...2487 
 William Gropp...2182 
 Rodriguez 6...2017 
 C++ Templates 3...1946 
 Trees...1939 
 Kamran Husain...1866 
 Secure Programming for Li...1792 
 Максвелл 5...1711 
 DevFS...1695 
 Part 3...1684 
 Stein-MacEachern-> Час...1632 
 Go Web ...1627 
 Ethreal 4...1619 
 Стивенс 9...1607 
 Arrays...1607 
 Максвелл 1...1594 
 FAQ...1539 
 
  01.01.2024 : 3621733 посещений 

iakovlev.org
 

Создание классов и объектов

Класс — это пакет с набором методов . Метод — это подпрограмма, встроенная в класс или объект. Метод использует ссылку на объект или имя класса, передаваемое ему в качестве первого аргумента. Объект — это ссылка на элемент данных. В отличие от других ссылок, этот элемент знает, к какому классу он относится. Рассмотрим пример класса Class1, для которого определен конструктор new. В этом конструкторе создается ссылка на анонимный хеш, который будет хранить данные объекта. package Class1; sub new { my $self = {}; bless($self); return $self; } return 1; Для создания объекта вызывается конструктор, который обычно имеет имя new. В следующем примере мы создаем объект определенного раннее класса Class1: use Class1; my $object = Class1->new(); Есть два типа методов: методы класса и методы объекта (методы экземпляров класса). Метод класса вызывается с помощью имени класса, а метод экземпляра класса — с помощью объекта (ссылки). package Class1; sub new { my $self = {}; bless($self); return $self; } sub name { my $class = shift; print "This is the class method.\n"; return $class; } return 1; use Class1 $classname = Class1->name(); $classname = Class1::name("Class1"); В следующем примере создается метод объекта data. Первый аргумент, передаваемый методу — это ссылка на сам объект. Мы используем ее, чтобы сохранить данные в анонимном хеше package Class1; sub new { my $self = {}; bless($self); return $self; } sub data { my $self = shift; if (@_) {$self->{DATA} = shift;} return $self->{DATA}; } return 1; use Class1 my $object1 = Class1->new(); $object1->data("Hello!"); print "Here is the text in the object: ", $object1->data(); Here is the text in the object: Hello! Хотя многие объектно-ориентированные языки программирования поддерживают приватные методы и переменные, (то есть, внутренние методы и переменные, недостижимые вне класса или объекта), Perl не позволяет делать этого явно. В следующем примере, мы отслеживаем полное число объектов, созданных для конкретного класса, запоминая его в переменной класса $total package Cdata; my $total = 0; sub new { $self = {}; $total++; return bless $self; } sub gettotal {return $total;} return 1; use Cdata; $object1 = Cdata->new; print "Current number of objects: ",$object1->gettotal, "\n"; $object2 = Cdata->new; print "Current number of objects: ", $object2->gettotal, "\n"; $object3 = Cdata->new; print "Current number of objects: ", $object3->gettotal, "\n"; Current number of objects: 1 Current number of objects: 2 Current number of objects: 3 Для выполнения команд Perl, связанных с уничтожением объектов, можно использовать деструкторы, — точнее, они начинают работать, когда объект готов к уничтожению. В Perl работает автоматическая система сборки мусора. Она уничтожает элементы и освобождает занимаемую ими память, когда они больше не нужны, — например, когда потеряна ссылка на данные, переменная выходит за границы области видимости, либо интерпретатор прекращает работу. В отличие от конструкторов, для деструкторов Perl имеется вполне определенное имя DESTROY: package Class1; sub new { my $type = {}; bless($self); return $self; } sub DESTROY { print "Object is being destroyed!\n"; } return 1; Наследование : В следующем примере от базового класса Class1 порождается дочерний Class2. В отличие от других объектно-ориентированных языков программирования, в Perl нельзя объявить члены класса как private или как protected package Class1; sub new { my $self = {}; bless($self); return $self; } sub gettext {return "Hello!\n";} return 1; package Class2; use Class1; @ISA = qw/Class1/; sub new { my $self = {}; bless($self); return $self; } return 1; use Class2; my $object1 = Class2->new(); print "The object says: ", $object1->gettext; The object says: Hello! Perl не проверяет структуру данных, создаваемую в конструкторе данного класса, даже на минимальную совместимость с методами, которые наследуются от родительских классов. Совместимость данных и методов — целиком на совести программиста. В этом примере конструктор класса Class2 можно унаследовать из класса Class1 (поскольку код Perl для этих конструкторов совпадает), но так как конструктор класса Class1 и возвращает объект класса Class1, а не класса Class2, это вызвало бы проблемы. Чтобы конструктор класса Class1 возвращал объекты класса Class2 (или любого другого, для которого Class1 является базовым), при работе с ним в контексте дочернего класса, его необходимо переписать. Для этой цели мы используем специальную форму функции bless с двумя аргументами, с которой мы еще не сталкивались. package Class1; sub new { my $class = shift; my $self = {}; $self->{NAME} = "Christine"; bless $self, $class; return $self; } return 1; package Class2; use Class1; @ISA = qw/Class1/; sub new { my $class = shift; my $self = {}; $self->{DATA} = 200; bless $self, $class; return $self; } return 1; use Class2; my $object1 = Class2->new(); print $object1->{NAME}, " has \$", $object1->{DATA}, "\n"; Christine has $200 В Perl вопрос о том, является ли метод виртуальным или нет, решается просто: все методы, вызываемые как методы классов, являются статическими. Наоборот, все методы, вызываемые как методы объектов, являются виртуальными. Тем самым свойство «виртуальности» зависит от способа вызова, и один и тот же метод может быть как виртуальным, так и статическим. Пример: package Class1; sub new { my $class = shift; my $self = {}; bless $self, $class; return $self; } sub gettext{ return "Hello!\n"; } sub printA { my $self = shift; print $self->gettext; # виртуальный вызов } sub printZ { my $self = shift; print Class1->gettext; # статический вызов } return 1; package Class2; # конструктор наследуется use Class1; @ISA = qw/Class1/; sub gettext{ # замещение метода return "Bye..."; } return 1; Использование : use Class1; use Class2; $object1 = Class1->new(); $object2 = Class2->new(); # статический вызов замещенного метода $object1->printZ; $object2->printZ; # виртуальный вызов замещенного метода $object1->printA; $object2->printA; Hello! Hello! Hello! Bye... Тот факт, что методы Perl, вызываемые как методы объекта, ведут себя как виртуальные методы традиционных языков программирования, позволяет нам еще больше усовершенствовать схему конструкторов (см. выше раздел «Наследование конструкторов»). А именно, разобьем конструктор на две части: метод new, который выделяет память под объект (анонимный хеш, анонимный массив или, даже, анонимный скаляр) и привязывает ссылку к классу, и init, который инициализирует выделенную память. Тогда мы можем замещать в дочерних классах только инициализирующую часть init, оставляя конструктор неизменным. Рассмотрим пример: package Class1; sub new { my $class = shift; my $self = {}; bless $self, $class; $self->init(@_); return $self; } sub init { my $self = shift; $self->{DATA} = shift; return $self; } return 1; package Class2; # конструктор new наследуется use Class1; @ISA = qw/Class1/; sub init { my $self = shift; $self->{DATA} = shift; $self->{VALUE} = shift; return $self; } return 1; use Class1; use Class2; $object1 = Class1->new(1024); $object2 = Class2->new(1024, 3.141592653589); В Perl можно создавать переменные класса, — то есть, переменные, недоступные вне класса, и содержащие значения, общие для всех объектов класса и доступные им. К сожалению, в Perl нет возможности организовать автоматическое наследование переменных класса, если только вы не организуете доступ к переменным базового класса с помощью наследуемых методов доступа. Единственный способ справиться с этой проблемой — это использовать для доступа к переменным класса только методы доступа (то есть, никогда не обращаться к ним напрямую), и при создании дочернего класса вручную повторить в его теле как переменные класса, так и методы доступа к ним. При этом в силу того, что методы объекта в Perl считаются виртуальными, новые переменные класса будут использоваться независимо от того, работает с ними метод дочернего или же метод, унаследованный от базового класса: package Class1; my $counter = 1; sub new { my $class = shift; my $self = {}; bless $self, $class; return $self; } sub getcounter{ return $counter; } sub setcounter{ $counter = shift; return $counter; } sub twicecounter{ # косвенный доступ my $self = shift; $my temp = $self->getcounter; $temp = 2*$temp; $self->setcounter($temp); return $temp; } return 1; package Class2; # конструктор наследуется my $counter = 100; use Class1; @ISA = qw/Class1/; sub getcounter{ return $counter; } sub setcounter{ $counter = shift; return $counter; } sub triplecounter{ # косвенный доступ my $self = shift; $my temp = $self->getcounter; $temp = 3*$temp; $self->setcounter($temp); return $temp; } return 1; use Class2; $object = Class2->new(); print $object->twicecounter, "\n"; print $object->triplecounter, "\n"; 200 300 В Perl производный класс может наследовать сразу от нескольких классов. Каждый из них должен быть объявлен с помощью команды use и перечислен в массиве @ISA. package Class0; sub printhi {print "Hi\n";} return 1; package Class1; sub printhello {print "Hello\n";} return 1; package Class1; use Class0; use Class1; $ISA = qw/Class0 Class1/; sub new { my $class = shift; my $self = {}; bless $self, $class; return $self; } return 1; use Class2; my $object = Class2->new(); $object->printhi; $object->printhello; Hi Hello
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье
Vourhey
  Good. Thanks
2008-04-18 11:45:01