Perl Moose 父类与子类一起演员表
package Point;
use Moose;
has 'x' => (isa => 'Int', is => 'rw');
has 'y' => (isa => 'Int', is => 'rw');
package Point3D;
use Moose;
extends 'Point';
has 'z' => (isa => 'Int', is => 'rw');
package main;
use Data::Dumper;
my $point1 = Point->new(x => 5, y => 7);
my $point3d = Point3D->new(z => -5);
$point3d = $point1;
print Dumper($point3d);
是否可以将父类强制转换为子类,例如 C++?在我的例子中,$point3d 现在是一个 Point,而不是包含 Point 的 Point3D。
package Point;
use Moose;
has 'x' => (isa => 'Int', is => 'rw');
has 'y' => (isa => 'Int', is => 'rw');
package Point3D;
use Moose;
extends 'Point';
has 'z' => (isa => 'Int', is => 'rw');
package main;
use Data::Dumper;
my $point1 = Point->new(x => 5, y => 7);
my $point3d = Point3D->new(z => -5);
$point3d = $point1;
print Dumper($point3d);
Is it possible to cast a parent to child class such as c++? In my examble is $point3d now a Point and not a Point3D include the Point.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
看一下 类:: CPAN 上的 MOP 文档,特别是
clone_object
和rebless_instance
方法:然后按如下方式使用它:
这也会小心对待新指定的
%args
就像它们是由构造函数传入的一样。例如,构建器、默认值和类型约束都在此构建过程中考虑。Take a look at the Class::MOP documentation on CPAN, especially the
clone_object
andrebless_instance
methods:And then use it like the following:
This will also take care to treat the newly specified
%args
as if they've been passed in by the constructor. E.g. builders, defaults, and type constraints are all considered during this build.您不需要在 Perl 中进行转换,因为它是一种动态语言。但在您的情况下,变量
$point3d
包含对脚本末尾的Point
对象的引用。您不能将其视为Point3D
因为它不是Point3D
。您可以手动转换它,但您无法将现有对象“重新制作”为不同的类。 (嗯,理论上你可以在 Perl 中使用,但你不应该这样做。)You do not need to cast in Perl, since it is a dynamic language. In your case though, the variable
$point3d
contains a reference to aPoint
object at the end of the script. You cannot treat this as aPoint3D
because it is not aPoint3D
. You could manually convert it, but you can't "remake" an existing object as a different class. (Well, you theoretically can in Perl, but you shouldn't.)好吧,
Dumper
应该告诉您$point3d
现在是一个Point
,而不是Point3D
,因为您的分配$point3d = $point1
使$point3d
成为对与$point1
相同的对象的第二个引用。最初由$point3d
引用的Point3D
实例现在丢失在空间中,引用计数为 0,使其符合垃圾回收条件。正如 cdhowie 所说,在 Perl 中你实际上并没有像在 C/C++ 中那样进行类型转换。我能想到的最接近的方法是依靠非 OO 调用约定并使用,例如,
Point3D::z($point1, 4)
来给出$point1
z 索引为 4,但这有点笨拙,您必须使用相同的语法来引用它的 z 索引。另请注意,使用此调用约定时,Point3D
必须实际定义z
方法[1],否则您将收到运行时错误,因为当您这样做时,继承不起作用,因为您将Point3D
作为包引用,而不是将$point1
作为对象引用。如果您想实际将
Point
变成Point3D
,您可以使用bless
轻松更改对象的实际类型(与使用的命令相同)首先将普通引用更改为对象,尽管它隐藏在示例代码中的 Moose 内部),但我怀疑手动重新祝福 Moose 对象会激怒 Moose。 (但是,如果是这种情况,我确信 Moose 提供了一种更安全的方法来更改对象的类。我只是没有充分使用 Moose 来知道它会是什么。)[1] ...或
AUTOLOAD
,但那是完全不同的蠕虫病毒。Well,
Dumper
should tell you that$point3d
is now aPoint
, not aPoint3D
, because your assignment of$point3d = $point1
makes$point3d
a second reference to the same object as$point1
. ThePoint3D
instance that was originally referenced by$point3d
is now lost in space with a refcount of 0, making it eligible for garbage collection.As cdhowie said, you don't really do typecasting in Perl the way you do in C/C++. The closest I can think of is to fall back on the non-OO calling convention and use, e.g.,
Point3D::z($point1, 4)
to give$point1
a z-index of 4, but that's kind of clumsy and you'd have to use the same syntax for any future references to it's z-index. Note also that, when using this calling convention,Point3D
must actually define az
method[1] or you'll get a runtime error because inheritance doesn't work when you do it this way because you're referring toPoint3D
as a package, not to$point1
as an object.If you want to actually make your
Point
into aPoint3D
, you can easily change the actual type of an object usingbless
(the same command used to change a plain reference into an object in the first place, although that's hidden inside of Moose in your example code), but I suspect that manually reblessing a Moose object would anger the Moose. (But, if that is the case, I'm sure Moose provides a safer way of changing an object's class. I just don't use Moose enough to know what it would be.)[1] ...or
AUTOLOAD
, but that's an entirely different can of worms.基本上,我赞同 cdhowie 和 Dave S. 的说法,但还要补充一件事。
如果你确实想将包含类
Point
的对象的$point3d
变成子类Point3D
的真实对象,那么正确的 OO 方法它是通过在Point3D
类中创建一个构造函数new_from_Point()
来获取Point
类的对象作为输入并创建一个Point3D
对象(它可能需要一个额外的“z”参数)。 C++ 等效项是一个签名为(const Point &, double &z=0.0)
的构造函数Basically, I am seconding what cdhowie and Dave S. said, but one more thing to add.
If you DO want to make
$point3d
which holds an object of classPoint
into a real object of subclassPoint3D
, the correct OO way of doing it is by creating a constructornew_from_Point()
inPoint3D
class, which takes an object of classPoint
as input and creates anPoint3D
object (it should probably take an extra "z" parameter). The C++ equivalent would be a constructor with a signature of(const Point &, double &z=0.0)