2013-10-27 93 views
3

有:正確的方式定義和轉換駝鹿屬性類型

package MyPath; 
use strict; 
use warnings; 
use Moose; 

has 'path' => (
    is => 'ro', 
    isa => 'Path::Class::Dir', 
    required => 1, 
); 
1; 

但要創建這個對象有兩種方式,如:

use strict; 
use warnings; 
use MyPath; 
use Path::Class; 
my $o1 = MyPath->new(path => dir('/string/path')); #as Path::Class::Dir 
my $o2 = MyPath->new(path => '/string/path'); #as string (dies - on attr type) 

當用「STR」稱呼它 - 希望將其在MyPath包內部轉換爲Class :: Path :: Dir,因此,兩個:$o1->path$o2->path應該返回祝福Path::Class::Dir

當我試圖擴展defin銀行足球比賽到下一個:

has 'path' => (
    is => 'ro', 
    isa => 'Path::Class::Dir|Str', #allowing both attr types 
    required => 1, 
); 

它不工作,仍然需要「有點」轉換StrPath::Class::Dir自動-內部的package MyPath ...

可能有人給我一些提示?

編輯:基於Oesor的提示,我發現比我更需要像成才:

coerce Directory, 
    from Str,  via { Path::Class::Dir->new($_) }; 

has 'path' => (
    is => 'ro', 
    isa => 'Directory', 
    required => 1, 
); 

但仍然還沒有知道如何正確地使用它...

一些更多的提示嗎?

回答

5

你要找的類型coersion。

use Moose; 
use Moose::Util::TypeConstraints; 
use Path::Class::Dir; 

subtype 'Path::Class::Dir', 
    as 'Object', 
    where { $_->isa('Path::Class::Dir') }; 

coerce 'Path::Class::Dir', 
    from 'Str', 
     via { Path::Class::Dir->new($_) }; 

has 'path' => (
    is  => 'ro', 
    isa  => 'Path::Class::Dir', 
    required => 1, 
    coerce => 1, 
); 
+0

謝謝 - 非常好。 – novacik

+1

你的'子類型'Path :: Class :: Dir'...'聲明可以更自然地寫成'class_type'Path :: Class :: Dir';'。 – hobbs