2013-10-27 65 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