Почему не был должен я использовать UNIVERSAL:: isa?

Вверху добавьте:

import import_export

Затем измените строку кода на:

hid = import_export.fields.Field(column_name='hid',attribute='hid', widget=ForeignKeyWidget(Library, 'name'))

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

17
задан Altreus 15 October 2008 в 10:57
поделиться

6 ответов

Основная проблема состоит в том, что, если Вы звоните UNIVERSAL::isa непосредственно, Вы обходите любые классы, которые перегрузились isa. Если те классы полагаются на перегруженное поведение (который они, вероятно, делают или иначе они не переопределили бы его), то это - проблема. Если Вы вызовете isa непосредственно на свой счастливый объект, то корректное isa метод назовут в любом случае (перегруженный, если он будет существовать, UNIVERSAL:: если не).

вторая проблема состоит в том, что UNIVERSAL::isa только выполнит тест, который Вы хотите на счастливой ссылке точно так же, как любое использование isa. Это имеет другое поведение для несчастливых ссылок и простых скаляров. Таким образом, Ваш пример, который не проверяет, благословлен ли $ref, не делает правильной вещи, Вы игнорируете состояние ошибки и используете UNIVERSAL альтернативное поведение. При определенных обстоятельствах это может вызвать тонкие ошибки (например, если Ваша переменная содержит название класса).

Рассмотрите:

use CGI;

my $a = CGI->new();

my $b = "CGI";

print UNIVERSAL::isa($a,"CGI");  # prints 1, $a is a CGI object.
print UNIVERSAL::isa($b,"CGI");  # Also prints 1!! Uh-oh!!

Так, таким образом, не используют UNIVERSAL::isa... Сделайте дополнительную проверку на ошибки и вызовите isa на свой объект непосредственно.

33
ответ дан 30 November 2019 в 10:21
поделиться

См. документы для UNIVERSAL:: isa и UNIVERSAL:: может для того, почему Вы не должны делать этого.

Короче говоря существуют важные модули с подлинной потребностью переопределить 'isa' (такой как Тест:: MockObject), и если Вы называете его как функцию, Вы повреждаете это.

Я должен сказать, my $self = shift if UNIVERSAL::isa($_[0], __PACKAGE__) не выглядит ужасно чистым мне - защитники анти-Perl жаловались бы на шум в линии.:)

9
ответ дан 30 November 2019 в 10:21
поделиться

Для прямого ответа на вопрос ответ внизу страницы, Вы связались с, а именно, что, если пакет определит isa метод, то вызов UNIVERSAL::isa непосредственно не назовет пакет isa метод. Это - очень неинтуитивное поведение с точки зрения объектной ориентации.

Остальная часть этого сообщения является просто большим количеством вопросов о том, почему Вы делаете это во-первых.

В коде как вышеупомянутое, в какой случаи, что конкретный isa протестировал бы сбой? т.е. если бы это - метод, в этом случае разве первым аргументом не был бы класс пакета или экземпляр этого?

я спрашиваю это, потому что интересно, существует ли законная причина, почему Вы хотели бы протестировать, является ли первым аргументом объект во-первых. т.е. Вы просто пытаетесь поймать людей, говорящих FooBar::method вместо FooBar->method или $foobar->method? Я предполагаю, что Perl не разработан для такого потворства, и если люди по ошибке будут использовать FooBar::method, то они узнают достаточно скоро.

Ваш пробег может варьироваться.

7
ответ дан 30 November 2019 в 10:21
поделиться

Все остальные сказали Вам , почему Вы не хотите использовать UNIVERSAL::isa, потому что это повреждается когда вещи перегрузка isa. Если они перешли ко всей привычке к перегрузке, что совершенно особый метод, Вы, конечно, хотите уважать ее. Несомненно, Вы могли делать это путем записи:

if (eval { $foo->isa("thing") }) {
     # Do thingish things
}

, потому что eval гарантии для возвращения false, если это выдает исключение и последнее значение иначе. Но это выглядит ужасным , и Вы не должны должны быть писать свой код забавными способами, потому что язык хочет Вас к. То, что мы действительно хотим, должно записать просто:

if ( $foo->isa("thing") ) {
     # Do thingish things
}

, Чтобы сделать это, мы должны были бы удостовериться, что $foo всегда объект. Но $foo могла быть строка, число, ссылка, неопределенное значение или все виды странного материала. Какая жалость Perl не может сделать все объект первого класса.

, О, ожидайте, это может...

use autobox;   # Everything is now a first class object.
use CGI;       # Because I know you have it installed.

my $x = 5;
my $y = CGI->new;

print "\$x is a CGI object\n" if $x->isa('CGI');   # This isn't printed.
print "\$y is a CGI object\n" if $y->isa('CGI');   # This is!

можно захватить автополе от CPAN. Можно также использовать его с лексическим контекстом, таким образом, все может быть объектом первого класса только для файлов или блоков, где Вы хотите использовать ->isa() без всех дополнительных головных болей. Это также делает партия [еще 1114], чем, что я покрыл в этом простом примере.

7
ответ дан 30 November 2019 в 10:21
поделиться

Принятие Вашего примера того, что Вы хотите смочь сделать, в методе объекта, Вы излишне параноики. Первый переданный объект всегда будет или ссылкой на объект соответствующего класса (или подкласс), или это будет название класса (или подкласс). Это никогда не будет ссылка никакого другого типа, если метод сознательно не назвали как функция. Можно, поэтому, безопасно просто использовать касательно различать эти два случая.

if (ref $_[0]) {
  my $self = shift;
  # called on instance, so do instancey things
} else {
  my $class = shift;
  # called as a class/static method, so do classy things
}
2
ответ дан 30 November 2019 в 10:21
поделиться

Верно. Он делает неправильную вещь для классов, которые перегружают isa. Просто используйте следующую идиому:

if (eval { $obj->isa($class) }) {

Она легко понимается и общепринята.

0
ответ дан 30 November 2019 в 10:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: