LINUX.ORG.RU

А чем бы сделать позднее статическое связывание в перле?


0

1

Например, в родительском классе я говорю:

package A;
....
__PACKAGE__->attr('foo');

Потом почкую потомка:

package B;
use base 'A';
__PACKAGE__->foo({
многоэтажный => 'хеш',
который => ['является', 'общим', 'для всех', ['экземпляров', 'данного', 'класса и его потомков']]
});
....

А потом делаю еще двоих:

package C;
use base 'B';

....

package D;
use base 'B';

__PACKAGE__->foo({'совсем' => 'другое значение'});

И вот когда я использую у себя в программе классы C и D одновременно, foo() каждого из них должен возвращать: для C — значение, объявленное в B, а для D — значение, объявленное в D.

В данный момент, когда я использую Class::Accessor::Class и mk_class_accessors, оба пакета будут возвращать из foo() значение, определенное в последнем из загруженных модулей, что, мягко говоря, неправильно.

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

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

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

★★★★★

в смысле если вам необходим «идеальный»(максимально приближенный) ООП инструмент, то могу Вам с уверенностью сказать, что перл таковым не является. Все его преимущества совсем не в ООП.

Jetty ★★★★★
()
Ответ на: комментарий от Jetty

Лять, филозопы доморощеные

В теме не спрашивается, какой язык лучше для ООП или нет (я знаю сам, что это Python).

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

Тоже мне, эксперты хреновы.

shimon ★★★★★
() автор топика
Ответ на: комментарий от arsi

Первый пост, шо ле, смотри.

Аналог питоновских class variables (не путать с instance variables) — которые наследуются нормально и нормально же перекрываются.

shimon ★★★★★
() автор топика
Ответ на: комментарий от shimon

> Первый пост, шо ле, смотри.

смотрел. увидел неудачную попытку решить некоторую задачу и сопли по этому поводу. что за задачу ты там пытался решать я так и не понял.

arsi ★★★★★
()
Ответ на: Лять, филозопы доморощеные от shimon

> В теме не спрашивается, какой язык лучше для ООП или нет (я знаю сам, что это Python).

Тоже мне, эксперты хреновы.

Автор нехренов эксперт.

anonymous
()

Позднее статическое связывание?

PKGA.pm

package PKGA;

use constant NAME => 'A_NAME';

sub new {
	bless {}, shift;
}

sub get_name {
	return ref(shift)->NAME;
}

1;

PKGB.pm

package PKGB;

use base 'PKGA';
use constant NAME => 'B_NAME';

1;

test.pl

use PKGA;
use PKGB;

$obj = PKGA->new();
warn $obj->get_name;

$obj = PKGB->new();
warn $obj->get_name;

output

A_NAME at test.pl line 5.
B_NAME at test.pl line 8.

Olegymous ★★★
()
Ответ на: Позднее статическое связывание? от Olegymous

omg, а инстансы зачем создавать? о_О

# PkgA.pm ------------------
package PkgA;

use strict;

my $foo = { hello=>['world'] };

sub foo { $foo }

1;

# PkgB.pm ------------------
package PkgB;

use strict;
use base 'PkgA';


1;

# PkgC.pm ------------------
package PkgC;

use strict;
use base 'PkgA';

my $foo = { perl=>'rulezz' };

sub foo { $foo }

1;

# test.pl ------------------
#!/usr/bin/perl

use strict;

use PkgA;
use PkgB;
use PkgC;

use Data::Dumper;
$Data::Dumper::Deepcopy = 1;

print Data::Dumper->Dump(
    [ PkgA->foo,   PkgB->foo,   PkgC->foo ],
    ['PkgA::foo', 'PkgB::foo', 'PkgC::foo']
);
$ ./test.pl
$PkgA::foo = {
               'hello' => [
                            'world'
                          ]
             };
$PkgB::foo = {
               'hello' => [
                            'world'
                          ]
             };
$PkgC::foo = {
               'perl' => 'rulezz'
             };
arsi ★★★★★
()
Ответ на: комментарий от arsi

> omg, а инстансы зачем создавать? о_О

Рискну предположить, что речь идет о нужном мне полиморфизме.

shimon ★★★★★
() автор топика

Не помогайте. Есть шанс, что так перл быстрее вымрет.

anonymous
()
Ответ на: комментарий от arsi

Эээ, ну тогда у меня так работает

package PKGA;
use Data::Dumper;

use constant NAME => 'A_NAME';

sub get_name {
	return shift->NAME;
}

package PKGB;

use base 'PKGA';
use constant NAME => 'B_NAME';

package main;

use PKGA;
use PKGB;

warn PKGA->get_name;
warn PKGB->get_name;

А у вас foo() дублируется в PkgC, это топикстартера явно не возбуждает.

Olegymous ★★★
()
Ответ на: комментарий от arsi

Вообще то оно для того и дублируется, чтобы показать что унаследованный метод возьмет константу не из своего родного класса, а из вызывающего.
Вообще говоря я только что узнал что это за «позднее статическое связывание» от любителей php. Здесь привёл аналогию на православном Perl.

Olegymous ★★★
()
Ответ на: комментарий от Olegymous

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

а если учесть, что «константа» и есть «метод»? ;) (ибо и то, и другое по сути — функции.)

# PkgA.pm ------------------
package PkgA;

use strict;
use constant foo => { hello=>['world'] };

1;

# PkgB.pm ------------------
package PkgB;

use strict;
use base 'PkgA';

1;

# PkgC.pm ------------------
package PkgC;

use strict;
use base 'PkgA';
use constant foo => { perl=>'rulezz' };

1;

(«test.pl» и результат — те же.)

arsi ★★★★★
()
Ответ на: комментарий от Olegymous

> поздним статическим связыванием

почитал по ссылке… виртуальные статические константные поля класса, так? тогда да, через «use constant», будет как в пхп ;)

arsi ★★★★★
()
Ответ на: комментарий от arsi

в смысле «use constant ЧегоТоТам => …; sub getЧегоТоТам { return shift->ЧегоТоТам }». %)

arsi ★★★★★
()
Ответ на: комментарий от Olegymous

Ровно то, что надо

Olegymous, если бы мог — угостил бы пивом.

use constant, just as advertised.

shimon ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.