Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 为什么从非Moo类继承的Moo对象被祝福到父对象';一些模块的软件包是什么?_Perl_Gobject Introspection_Moo - Fatal编程技术网

Perl 为什么从非Moo类继承的Moo对象被祝福到父对象';一些模块的软件包是什么?

Perl 为什么从非Moo类继承的Moo对象被祝福到父对象';一些模块的软件包是什么?,perl,gobject-introspection,moo,Perl,Gobject Introspection,Moo,我正在尝试使用和在Perl中创建Gtk3应用程序。Gtk中有一个非Moo类,Gtk::ApplicationWindow,我使用扩展“Gtk::ApplicationWindow”通过Moo对其进行子类化。问题是,当创建该子类的对象时,它仍然是父类的类型,即Gtk::ApplicationWindow 我尝试了同样的方法,将我自己的非Moo类子类化,从这个子类创建的对象的类型是正确的。造成这种差异的原因是什么 use v5.10; use strict; use warnings; # Imp

我正在尝试使用和在Perl中创建Gtk3应用程序。Gtk中有一个非Moo类,
Gtk::ApplicationWindow
,我使用
扩展“Gtk::ApplicationWindow”
通过Moo对其进行子类化。问题是,当创建该子类的对象时,它仍然是父类的类型,即
Gtk::ApplicationWindow

我尝试了同样的方法,将我自己的非Moo类子类化,从这个子类创建的对象的类型是正确的。造成这种差异的原因是什么

use v5.10;
use strict;
use warnings;

# Import the Gtk classes (non-Moo)
use Glib::Object::Introspection;
Glib::Object::Introspection->setup(basename => 'Gtk', version => '3.0', package => 'Gtk');
Glib::Object::Introspection->setup(basename => 'Gio', version => '2.0', package => 'Gio');

#################################################
{
    # A dummy non-Moo class
    package ClassNonMoo;
    sub new { bless {}, shift; }
}

{
    # Moo class extending the dummy class
    package ClassMoo;
    use Moo;

    extends 'ClassNonMoo';

    sub FOREIGNBUILDARGS {
        my ($class, %args) = @_;
        return ($args{app});
    }
}
#################################################

{
    # Moo class extending Gtk::ApplicationWindow
    package ClassMooGtkAppWin;
    use Moo;

    extends 'Gtk::ApplicationWindow';

    sub FOREIGNBUILDARGS {
        my ($class, %args) = @_;
        return ($args{app});
    }
}

#################################################

# Create objects of ClassMoo and ClassMooGtkAppWin
sub create_objects {
    my ($app) = @_;

    my $o1 = ClassMoo->new( app => $app );
    my $o2 = ClassMooGtkAppWin->new( app => $app );

    say "o1 = $o1\no2 = $o2";
    # Output:
    # o1 = ClassMoo=HASH(0x2f7bc50)
    # o2 = Gtk::ApplicationWindow=HASH(0x2f7bd40)
    #
    # Shouldn't o2 be of the type ClassMooGtkAppWin ?

    exit(0);
}

# We can create a GtkApplicationWindow only after creating a GtkApplication and
# running it. This code just ensures that create_object() is called once the
# application is 'active'.
my $app = Gtk::Application->new('org.test', 'flags-none');
$app->signal_connect(activate => sub { create_objects($app) });
$app->run();

我找不到要验证的Gtk::ApplicationWindow,但它可能会验证

sub new {
   my ($class) = @_;
   return bless({});
}
而不是

sub new {
   my ($class) = @_;
   return bless({}, $class);
}
“新”构造函数需要以观察调用方的实际类(与子类一起工作)的方式编写,但它们也可以硬编码使用哪个类创建对象

比较:

package MyClass;

# Considerate of subclassing
sub new {
    my $class = shift;
    return bless {}, $class;
}

# Doesn't give a shit
sub new {
    my $class = shift;
    return bless {};
}
Glib看起来像是围绕C库的XS模块包装器,它可能会硬编码该类

您可能只需要尝试将对象重新祝福(对构建的对象再次调用祝福)到您的实际子类中。不确定这将如何与Moo一起工作,但可能是在构建方法中

您也可以跳过继承而改用委派。创建一个属性来保存原始窗口对象,然后将所有方法委托给它,子类中的方法除外

在Moose(非Moo)中,您可以使用正则表达式执行此操作:


不知道如何与Moo很好地合作。

很好的发现。我用DateTime测试过,效果很好。谢谢,看起来确实如此。Gtk::ApplicationWindow的绑定是在运行时(或编译时?)由Glib::Object::Introspection自动生成的,它可能没有正确地支持hashref。啊,我现在了解了模块的功能。不幸的是,修复模块并不是一件小事,至少对不熟悉其内部工作的人来说是这样。是的,情况确实如此,在
BUILD
sub中重新祝福可以使事情正常工作,子类的行为也应该如此。非常感谢。