8

GObject IntrospectionMooを使用して Perl で Gtk3 アプリケーションを作成しようとしています。Gtk からの非 Moo クラスがありGtk::ApplicationWindow、これを Moo を使用してサブクラス化しextends 'Gtk::ApplicationWindow'ます。問題は、そのサブクラスのオブジェクトが作成されたときに、親クラスの型のままであるということ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();
4

2 に答える 2

4

「新しい」コンストラクターは、呼び出し元の実際のクラス (サブクラス化で機能する) を観察する方法で記述する必要がありますが、オブジェクトを作成するクラスをハードコードすることもできます。

比較:

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 モジュール ラッパーのように見え、クラスをハードコーディングする可能性があります。

オブジェクトを実際のサブクラスに re-bless (構築されたオブジェクトで再度 bless を呼び出す) しようとすることもできます。それが Moo でどのように機能するかは正確にはわかりませんが、おそらく BUILD メソッドで機能します。

継承をスキップして、代わりに委任を使用することもできます。元の Window オブジェクトを保持する属性を作成し、サブクラス内の独自のものを除いて、すべてのメソッドをそれに委譲します。

Moose (Moo ではない) では、正規表現でこれを行うことができます: https://metacpan.org/pod/Moose#handles-ARRAY-HASH-REGEXP-ROLE-ROLETYPE-DUCKTYPE-CODE

Moo でそれをうまく行う方法がわかりません。

于 2015-09-30T19:33:21.647 に答える
2

検証するGtk::ApplicationWindowが見つかりませんが、おそらくそうです

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

それ以外の

sub new {
   my ($class) = @_;
   return bless({}, $class);
}
于 2015-09-30T14:50:08.040 に答える