创建自定义Moose属性类型

时间:2018-04-06 17:13:21

标签: perl moose

我正在尝试简化我的Imports System.Runtime.InteropServices Public Class Form1 Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load SetCueText(TextBox1, "Enter Name here") End Sub End Class Public Module CueBannerText <DllImport("user32.dll", CharSet:=CharSet.Auto)> _ Private Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As Integer, <MarshalAs(UnmanagedType.LPWStr)> ByVal lParam As String) As Int32 End Function Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As IntPtr, ByVal hWnd2 As IntPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As IntPtr Private Const EM_SETCUEBANNER As Integer = &H1501 Public Sub SetCueText(cntrl As Control, text As String) If TypeOf cntrl Is ComboBox Then Dim Edit_hWnd As IntPtr = FindWindowEx(cntrl.Handle, IntPtr.Zero, "Edit", Nothing) If Not Edit_hWnd = IntPtr.Zero Then SendMessage(Edit_hWnd, EM_SETCUEBANNER, 0, text) End If ElseIf TypeOf cntrl Is TextBox Then SendMessage(cntrl.Handle, EM_SETCUEBANNER, 0, text) End If End Sub End Module 类的一类属性的定义。例如,考虑一类可以标记为Moose的属性,这里是一个这样的属性的示例:

private

想象一下,类package MyPkg; use Moose; has some_attribute => ( is => 'ro', isa => 'Str', lazy => 1, init_arg => undef, # prevent from being set by constructor builder => "_set_some_attribute" ); sub _set_some_attribute { my ( $self ) = @_; return "value_of_some_attribute"; } sub some_method_that_uses_some_attribute { my ( $self ) = @_; return "The value of some attribute: " . $self->some_attribute; } package main; use feature qw(say); use strict; use warnings; my $o = MyPkg->new(); say $o->some_method_that_uses_some_attribute; 的属性some_attribute属于一组可以标记为MyPkg的属性,其中所有属性类型为private的属性都是private并且不能由构造函数设置。也就是说,我想简化:

lazy

这样的事情

package MyPkg;
use Moose;
has some_attribute => (
    is       => 'ro',
    isa      => 'Str',
    lazy     => 1,
    init_arg => undef, # prevent from being set by constructor
    builder  => "_set_some_attribute"
);

这可以用package MyPkg; use Moose; use MyMooseAttributeExtensions; # <-- some Moose extension that I have to write has some_attribute => (is => 'ro', isa => 'Str', private => 1 ); 吗?

1 个答案:

答案 0 :(得分:4)

根据Moose::Manual::Attribute

  

如果您有许多仅按名称不同的属性,则可以   立即声明它们:

package Point;  
use Moose;

has [ 'x', 'y' ] => ( is => 'ro', isa => 'Int' );
     

另外,因为has只是一个函数调用,所以你可以在循环中调用它:

for my $name ( qw( x y ) ) {  
    my $builder = '_build_' . $name;  
    has $name => ( is => 'ro', isa => 'Int', builder => $builder );
}

还有lazy_build属性,请参阅Moose::Meta::Attribute,但文档说明:&#34;请注意,强烈建议不要使用此功能&#34; < / p>

最后一个选项是使用扩展包。 我想这已经存在于CPAN的某个地方了,但我找不到了,所以这是我尝试实现Moose扩展名:

package MyMooseAttributeExtensions;
use strict;
use warnings;

our %orig_has;  # save original 'has' sub routines here

sub import {
    my $callpkg = caller 0;
    {
        no strict 'refs';
        no warnings 'redefine';
        $orig_has{$callpkg} = *{$callpkg."::has"}{CODE};
        *{$callpkg."::has"} = \&private_has;
    }
    return;
}

sub private_has {
    my ($attr, %args) = @_;

    my $callpkg = caller 0;
    if (exists $args{private} ) {
        delete $args{private};
        %args = (
            %args,
            lazy     => 1,
            init_arg => undef, # prevent from being set by constructor
            builder  => "_set_$attr"
        );
    }
    $orig_has{$callpkg}->($attr, %args);
}

1;