2009-11-01 16 views
5

xem xét như sau:Vấn đề với mixins trong một MooseX :: lớp NonMoose

package MyApp::CGI; 

use Moose; 
use MooseX::NonMoose; 
use Data::Dumper; 

extends 'CGI::Application'; 

BEGIN { 
    print "begin isa = " . Dumper \@MyApp::CGI::ISA; 
}; 

print "runtime isa = " . Dumper \@MyApp::CGI::ISA; 

... 

Sản lượng khi điều này biên dịch là:

begin isa = $VAR1 = [ 
      'Moose::Object' 
     ]; 
runtime isa = $VAR1 = [ 
      'CGI::Application', 
      'Moose::Object' 
     ]; 

Tại sao tôi chăm sóc? Bởi vì khi tôi cố gắng để use một CGI :: Ứng dụng :: Plugin :: * lớp, nó hy vọng tôi được kế thừa từ CGI::Application tại thời gian biên dịch rồi. Lớp plugin cố gắng gọi add_callback là một phương thức lớp học trên lớp của tôi, nhưng không thể, bởi vì @ISA của tôi chưa được thiết lập.

Cách tốt nhất để giải quyết vấn đề này là gì? Việc tinh chỉnh @ISA theo cách thủ công trong khối BEGIN có gây trở ngại cho MooseX::NonMoose không?

Sửa

Sau đây xuất hiện để làm việc, nhưng tôi thấy nó tấn công:

package MyApp::CGI; 

use Moose; 
use MooseX::NonMoose; 

use base 'CGI::Application'; 
extends 'CGI::Application'; 

Tôi không biết đủ (hoặc bất cứ điều gì, thực sự) về internals Moose biết nếu điều này là một ý kiến ​​hay.

+5

BEGIN {extends ...}. – jrockway

+1

(Đáng chú ý rằng "sử dụng" như một từ đồng nghĩa cho BEGIN là một mô hình phổ biến. Xem thêm: "sử dụng ok ...") – jrockway

+0

jrockway: đó phải là câu trả lời, không phải là một chú thích – ysth

Trả lời

5

Tôi không tìm thấy use base 'CGI::Application'; extends 'CGI::Application'; là khủng khiếp ghê sợ bởi vì nó một cách chính xác những gì bạn cần:

  • Tại thời gian biên dịch, @ISA chứa 'CGI::Application', mà chính xác đáp ứng các yêu cầu sử dụng của CGI :: Ứng dụng :: Plugin :: *
  • Khi chạy, lớp học của bạn là con số Moose hậu duệ của CGI::Application, với tất cả các lợi ích sau đó (có thể thiết kế thành phần của lớp học của bạn với tính ưu việt siêu tốt). Chỉ sau khi dòng extends 'CGI::Application' gặp phải rằng mọi công việc được thực hiện (tức là phương thức được gọi trên lớp của bạn) dựa trên công việc được thực hiện theo tuyên bố extends: lớp học của bạn xuống từ Moose::Object và bạn đã cài đặt một lớp meta.

Điều đó nói rằng, giải pháp jrockway cũng nên làm việc:

BEGIN { extends 'CGI::Application' } 

... nơi bạn có được tất cả các meta tốt lành phép Moosey chỉ là một chút trước thời hạn từ khi bạn cần nó, và nó không nên trước tiên là trước, miễn là bạn đã gọi use Mooseuse MooseX::NonMoose để xác định extends.

(Phụ lục: Bây giờ tôi đang cân nhắc các phức tạp phức tạp của việc tạo khả năng phân tích cú pháp của từ khóa tại thời gian biên dịch được phân tích ngay lập tức chẳng hạn như chúng được gói trong khối BEGIN. Moose.pm tuyên bố use compiletime qw(extends). Nó sẽ là một đoạn tốt đẹp của đường cú pháp chắc chắn.)

+1

Sử dụng khối lệnh 'BEGIN'. Tôi sẽ đưa ++ cho jrockaway nhưng anh ấy không đăng nó trong một câu trả lời. :) – friedo

+1

Ether: Devel :: BeginLift thực hiện điều đó. – jrockway

+0

@jrockway: ooh, đồ chơi mới để chơi với! cảm ơn! – Ether