2010-03-12 27 views
6

Có thể thay thế phương pháp của đối tượng Moose trong thời gian chạy không? Bằng cách nhìn vào mã nguồn của Class::MOP::Method (mà Moose::Meta::Method thừa hưởng từ) Tôi kết luận rằng bằng cách làmLàm cách nào để thay thế một phương thức của đối tượng Moose trong thời gian chạy?

$method->{body} = sub{ my stuff } 

tôi sẽ có thể thay thế trong thời gian chạy một phương pháp của một đối tượng. Tôi có thể sử dụng phương pháp này bằng cách sử dụng

$object->meta->find_method_by_name(<method_name>); 

Tuy nhiên, điều này không hoàn toàn hiệu quả.

Có thể tưởng tượng được để sửa đổi các phương pháp trong thời gian chạy không? Và, cách để làm điều đó với Moose là gì?

Trả lời

4

Moose hay không, điều đó nghe có vẻ không hay.

Thay vào đó, hãy thiết kế đối tượng của bạn để có người truy cập cho phương pháp. Ví dụ: người dùng trong lớp của bạn có thể sử dụng My::Frobnicator->frobnicator->() để nhận và gọi phương thức frobnicator và sử dụng My::Frobnicator->frobnicator(sub { }) để đặt.

+1

Sinan ý tưởng rất hay :) cảm ơn bạn – xxxxxxx

4

Ý tưởng của Sinan là một khởi đầu tuyệt vời.

Nhưng với một chút tinh chỉnh, bạn có thể sử dụng phương thức truy cập phương pháp của mình giống như sử dụng phương pháp thông thường.

#!/usr/bin/perl 
use strict; 
use warnings; 
use Carp; 

my $f = Frob->new; 

$f->frob(
    sub { 
     my $self = shift; 
     print "$self was frobbed\n"; 
     print Carp::longmess('frob') 
    } 
); 

print "\nCall frob as normal sub\n"; 
$f->frobit; 

print "\nGoto frob\n"; 
$f->goto_frob; 

BEGIN { 
    package Frob; 
    use Moose; 

    has 'frob' => (
     is => 'rw', 
     isa => 'CodeRef', 
    ); 

    sub frobit { 
     &{$_[0]->frob}; 
    } 
    sub goto_frob { 
     goto $_[0]->frob; 
    } 

} 

Hai phương pháp trong Frob rất giống nhau.

  • frobit chuyển tất cả các đối số, bao gồm cả người yêu cầu mã ref.
  • goto_frob chuyển tất cả các đối số, kể cả người invocant vào mã ref và thay thế khung ngăn xếp của goto_frob bằng mã refs.

Việc sử dụng tùy thuộc vào thứ bạn muốn trong ngăn xếp.


Về munging lưu trữ cơ thể của một đối tượng Class::MOP::Method, như vậy $method->{body} = sub { 'foo' }:

Không bao giờ là một ý tưởng tốt để vi phạm đóng gói khi bạn đang làm OOP. Đặc biệt không phải khi bạn đang làm việc với các hệ thống đối tượng phức tạp như Moose và Class :: MOP. Nó yêu cầu rắc rối. Đôi khi, không có cách nào khác để có được những gì bạn muốn, nhưng ngay cả sau đó, vi phạm đóng gói vẫn là một ý tưởng tồi.

3

Sử dụng previously được đề cập MooseX::SingletonMethod bạn có thể thay thế phương thức đối tượng.

Ví dụ:

{ 
    package Foo; 
    use MooseX::SingletonMethod; 
    sub foo { say 'bar' }; 
} 

my $bar = Foo->new; 
my $baz = Foo->new; 

# replace foo method just in $baz object 
$baz->add_singleton_method(foo => sub { say 'baz' }); 

$bar->foo;  # => bar 
$baz->foo;  # => baz 

Cũng thấy điều này SO câu trả lời cho What should I do with an object that should no longer be used in Perl?, trong đó cho thấy cách này có thể đạt được sử dụng vai trò Moose.

/I3az/

Các vấn đề liên quan