Я в настоящее время использую блок eval
для тестирования этого, я установил атрибут как только для чтения. Существует ли более простой способ сделать это?
Пример из рабочего кода:
#Test that sample_for is ready only
eval { $snp_obj->sample_for('t/sample_manifest2.txt');};
like($@, qr/read-only/xms, "'sample_for' is read-only");
ОБНОВЛЕНИЕ
Благодаря friedo, Эфиру и Robert P для их ответов и к Эфиру, Robert P и jrockway для их комментариев.
Мне нравится, как ответ Эфира гарантирует это $is_read_only
только истинное или ложное значение (т.е. но никогда coderef) путем отрицания его с a !
. Двойное отрицание также обеспечивает это. Таким образом можно использовать $is_read_only
в is()
функция, без него распечатывающий coderef.
См. ответ P Robert ниже для самого полного ответа. Все были очень полезны и основывались на ответах друг друга и комментариях. В целом, я думаю, что он помог мне больше всего, следовательно его теперь отмечен принятый ответ. Снова, благодаря Эфиру, Robert P, friedo, и jrockway.
В случае, если Вы могли бы задаваться вопросом, как я сделал сначала, вот документация о различии между get_attribute
и find_attribute_by_name
(от Класса:: MOP:: Класс):
$metaclass->get_attribute($attribute_name)
This will return a Class::MOP::Attribute for the specified $attribute_name. If the
class does not have the specified attribute, it returns undef.
NOTE that get_attribute does not search superclasses, for that you need to use
find_attribute_by_name.
Технически атрибуту не обязательно иметь метод чтения или записи. Чаще всего будет, но не всегда. Пример (любезно украденный из комментария jrockway ) ниже:
has foo => (
isa => 'ArrayRef',
traits => ['Array'],
handles => { add_foo => 'push', get_foo => 'pop' }
)
Этот атрибут будет существовать, но не будет иметь стандартных читателей и писателей.
Таким образом, чтобы в каждой ситуации проверить, что атрибут был определен как is => 'RO'
, вам необходимо проверить как метод записи, так и метод чтения. Вы можете сделать это с помощью этой подпрограммы:
# returns the read method if it exists, or undef otherwise.
sub attribute_is_read_only {
my ($obj, $attribute_name) = @_;
my $attribute = $obj->meta->get_attribute($attribute_name);
return unless defined $attribute;
return (! $attribute->get_write_method() && $attribute->get_read_method());
}
В качестве альтернативы вы можете добавить двойное отрицание перед последним return
, чтобы логически преобразовать возвращаемое значение:
return !! (! $attribute->get_write_method() && $attribute->get_read_method());
Как описано в Class :: MOP :: Attribute :
my $attr = $this->meta->find_attribute_by_name($attr_name);
my $is_read_only = ! $attr->get_write_method();
$ attr-> get_write_method ()
получит метод записи (созданный вами или созданный) или undef, если его нет.
Sie sollten dies aus der Metaklasse des Objekts abrufen können:
unless ( $snp_obj->meta->get_attribute( 'sample_for' )->get_write_method ) {
# no write method, so it's read-only
}
Weitere Informationen finden Sie unter Class::MOP::Attribute.