Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
      Languages 
      Kernels 
      Packages 
      Books 
      Tests 
      OS 
      Forum 
      Математика 
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
 Linux Kernel 2.6...3207 
 Rodriguez 3...2412 
 Сетунь...1544 
 FAQ...1516 
 M.Pilgrim->Часть 2...1508 
 M.Pilgrim->Часть 1...1502 
 Clickhouse...1480 
 William Gropp...1478 
 C++ Patterns 3...1478 
 Trees...1469 
 Стивенс 9...1469 
 Ethreal 4...1460 
 Httpd-> История Ap...1459 
 Максвелл 5...1454 
 Rodriguez 6...1452 
 Ethreal 3...1449 
 Ext4 FS...1448 
 Part 3...1448 
 Rodriguez 8...1447 
 Stewens -> IPC 9...1446 
 
  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