2

最近Mooseをv1.15にアップグレードしたところ、使用しているモジュールのセットが機能しなくなったことがわかりました。私が得るエラーは次のとおりです。

You cannot coerce an attribute (source) unless its type (GOBO::Node) has a coercion at
/opt/local/lib/perl5/site_perl/5.12.0/darwin-multi-2level/Moose/Meta/Role/Application/ToClass.pm line 142

私はいくつかの考えられるエラーの原因を見ることができ、問題を解決する方法についてのアドバイスをいただければ幸いです。

GOBO::Nodeのコードの最初のビットは次のようになります。

package GOBO::Node;
[...]
extends 'GOBO::Base';
with 'GOBO::Labeled';
with 'GOBO::Attributed';

coerce 'GOBO::Node'
  => from 'Str'
  => via { new GOBO::Node(id=>$_) };

has 'source' => (is => 'rw', isa => 'GOBO::Node');

このパッケージで使用されるロールには、GOBO :: Nodesの属性もあり、エラーメッセージに記載されている属性「source」もその1つです。

  • GOBO :: Nodeに強制がある理由の一部は、新しいノードを作成するときのショートカットのようです。強制するよりもBUILDARGSを使用する方が良いでしょうか?

  • 複数のパッケージで強制を使用できるようにする場合は、どこに強制を配置する必要がありますか?(例)GOBO :: Attributedに強制を追加すると、すでに存在しているという警告が表示されます。ただし、強制がないと、上記のように強制できないという警告が表示されます。

  • サブタイプの個別のパッケージがあります。GOBO :: Nodeのサブタイプ(GOBO :: Node :: ProtoNodeなど)と強制を作成し、それを属性に使用してGOBO :: Nodesにする方がよいでしょうか?

この問題に関するヘルプやアドバイスをありがとうございます!

4

2 に答える 2

9

貼り付けたサンプルコードは、実際にはエラーを引き起こしません。そこsourceに書かれている属性は、何も強制しようとはしません。ただし、あなたが言及した役割の1つには、coerce => 1定義済みの属性があると思います。

Mooseタイプでは、したがって強制はグローバルです。Mooseが動的にクラスを構築するという事実と組み合わせると、ここで見られる奇妙な動作になります。タイプを最初に使用する前に、強制の定義をどこかに移動する必要がありますGOBO::Node。通常、これはサブタイプのパッケージを作成し(すでに持っていることに注意してください)、それをできるだけ早く(経由でuse)含めることによって行われます。

強制定義をこのサブタイプのパッケージに移動しGOBO::Node、強制が必要なすべての場所で使用されていることを確認するだけで、問題が解決するはずです。

他の質問に答えるには:

  • BUILDARGS一般的に、強制ははるかにきめの細かいツールであるため、強制を使用することをお勧めします。ここに示している使用法は、適切な強制使用法の教科書の例であるため、それを変更する本当の理由はありません。

  • 上記のように、一般的な答えは、別の名前空間(MyApp::TypeLibrary)でライブラリパッケージを構築し、そのパッケージを、タイプを使用できるようにするクラスの先頭に含めることです。Perlは、すでにコンパイルされているパッケージを再コンパイルしません。つまり、この場合、既存の強制について発生したエラーはトリガーされません。

  • 提供した例に基づいて、新しいサブタイプを作成する必要はありません。GOBO:: Nodeはすでに機能しているはずです。新しいサブタイプがなければ、これは事実上最後のサブタイプと同じ答えです。はい、サブタイプライブラリを使用します。

それがお役に立てば幸いです。

于 2010-10-15T20:09:57.733 に答える
6

一般的な解決策は、型の制約とその強制を宣言するためだけに別のファイルを用意することです。特定のクラスがロードされていることを確認する必要がある場合(たとえば、強制するため)、強制関数内でそれを要求します。

だから、次のようなもの:

package GOBO::Types;
use Moose::Util::TypeConstraints;
class_type 'GOBO::Node';
coerce 'GOBO::Node',
    from 'Str',
    via { require GOBO::Node; GOBO::Node->new(id => $_) };

このタイプライブラリは、読み込み順序を気にせずにどこでも使用でき、すべてのタイプがすでに定義されていることを確認できます。特にclass_type、Mooseがタイプ制約名を解決しようとするため、定義されていないタイプがある場合は特に重要です。まだ定義されていません。

代わりにここで強制を使用するBUILDARGSことは間違いなく正しいことです。それははるかに再利用可能です。

于 2010-10-15T20:15:25.130 に答える