在 Moose 中,如何使类的构造函数返回子类的实例?

发布于 2024-09-27 09:18:08 字数 815 浏览 8 评论 0原文

可能的重复:
如何让 Moose 返回子类实例而不是它自己的类,以实现多态性

假设我有两个相关的类 MyClass::A 和 MyClass::B,它们都是 MyClass 的子类。我希望 MyClass 的构造函数获取文件名,读取文件,并根据文件的内容确定文件是 A 类型还是 B 类型。然后,它应该构造一个适当子类的对象并返回它。 编辑:实际上,它应该调用适当子类的构造函数并返回结果。

例如,在此代码之后,

my $filename = "file_of_type_A.txt";
my $object = MyClass->new($filename);

$object 应该是 MyClass::A 的实例。这似乎是有效的行为,因为 $object->isa('MyClass') 将始终返回 true。我正在考虑使用内省来获取 MyClass 的所有子类的列表,然后尝试依次构造每个子类,直到成功为止。但是,我没有找到修改 Moose 构造函数来执行此操作的方法。 BUILDARGS 和 BUILD 挂钩似乎都不合适。

那么如何修改 Moose 类的构造函数来选择适当的子类并将构造委托给该子类呢?

Possible Duplicate:
How to have Moose return a child class instance instead of its own class, for polymorphism

Suppose I have two related classes MyClass::A and MyClass::B that are both subclasses of MyClass. I would like the constructor for MyClass to take a filename, read the file, and based on the contents of the file, decide whether the file is of type A or B. Then, it should construct an object of the appropriate subclass and return it. Edit: Actually, it should call the constructor of the appropriate subclass and return the result.

So for example, after this code,

my $filename = "file_of_type_A.txt";
my $object = MyClass->new($filename);

$object should be an instance of MyClass::A. This seems like valid behavior, because $object->isa('MyClass') will always return true. I was thinking of using introspection to get a list of all subclasses of MyClass, and then trying to construct each in turn, until one succeeds. However, I don't see a way to modify the Moose constructor to do this. Neither the BUILDARGS nor BUILD hooks seem appropriate.

So how can I modify a Moose class's constructor to select an appropriate subclass and delegate construction to that subclass?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绝不放开 2024-10-04 09:18:08

正如 Ether 上面所说,你应该有一个工厂方法来完成这个任务。我喜欢将工厂方法与它生成的东西放在一个单独的包/类中,通常这是一个没有属性或构造函数的虚拟类,但如果你想做一些事情,比如跟踪你所做的事情,你可以创建一个实际的工厂对象。

package MyFile::Factory;

sub make_file_object {
    my $class = shift;
    my $filepath = shift;

    my $type = $class->determine_file_type( $filepath );
    my $file_class = $class->get_class_for_file_type( $type );

   return $file_class->new( $filepath, @_ );
}

# implement those other methods down here.

1;

As Ether said above, you should have a factory method do this task. I like to put the factory method in a separate package/class from the things it produces Usually this is a virtual class that has no attributes or constructor, but if you want to do things like keep track of what you have made, you can create an actual factory object.

package MyFile::Factory;

sub make_file_object {
    my $class = shift;
    my $filepath = shift;

    my $type = $class->determine_file_type( $filepath );
    my $file_class = $class->get_class_for_file_type( $type );

   return $file_class->new( $filepath, @_ );
}

# implement those other methods down here.

1;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文