2013-09-23 56 views
6

Tôi đang cố gắng triển khai lớp Moose :: Vai trò hoạt động giống như lớp trừu tượng sẽ trong Java. Tôi muốn thực hiện một số phương thức trong Role, nhưng sau đó có khả năng ghi đè lên các phương thức đó trong các lớp cụ thể. Nếu tôi thử điều này bằng cách sử dụng cùng một phong cách hoạt động khi tôi mở rộng các lớp, tôi gặp lỗi Cannot add an override method if a local method is already present. Dưới đây là một ví dụ:Làm thế nào để ghi đè lên một phụ trong một Moose :: Vai trò?

lớp trừu tượng của tôi:

package AbstractClass; 

use Moose::Role; 

sub my_ac_sub { 

    my $self = shift; 

    print "In AbstractClass!\n"; 
    return; 
} 

1; 

lớp bê tông của tôi:

package Class; 

use Moose; 

with 'AbstractClass'; 

override 'my_ac_sub' => sub { 

    my $self = shift; 

    super; 
    print "In Class!\n"; 
    return; 
}; 

__PACKAGE__->meta->make_immutable; 
1; 

Và sau đó:

use Class; 

my $class = Class->new; 
$class->my_ac_sub; 

Tôi có làm điều gì sai? Là những gì tôi đang cố gắng để thực hiện nghĩa vụ phải được thực hiện một cách khác nhau? Là những gì tôi đang cố gắng để làm không phải được thực hiện ở tất cả?

+0

Sử dụng lớp trừu tượng để mô hình hóa lớp trừu tượng! Điều này chỉ yêu cầu bạn thực hiện việc xây dựng không thể (ví dụ: cung cấp BUILDALL để phát hiện lỗi). – amon

+1

Có lẽ cách Moose để làm điều này là có 'require 'my_ac_sub';' trong Role, * not * phương thức "virtual". Moose :: Vai trò sau đó sẽ kiểm tra nó đã được tạo thành một lớp với phương pháp có sẵn, –

+1

Tôi đã thử chạy mã và sau đó thay thế ghi đè bởi chỉ 'my_ac_sub' phụ và đột nhiên nó hoạt động như mong đợi. Có gì sai với "sửa chữa" đó không? (Disclaimer: Tôi mới đến Moose). – Dallaylaen

Trả lời

4

Hóa ra tôi đã sử dụng nó không đúng cách. Tôi đã mở a ticket và được hiển thị đúng cách để thực hiện việc này:

package Class; 

use Moose; 

with 'AbstractClass'; 

around 'my_ac_sub' => sub { 

    my $next = shift; 
    my $self = shift; 

    $self->$next(); 
    print "In Class!\n"; 
    return; 
}; 

__PACKAGE__->meta->make_immutable; 
1; 

Thực hiện thay đổi này có hiệu quả mong muốn.

2

Some time ago, tôi đã thực hiện việc này bằng cách có vai trò chỉ bao gồm các câu hỏi requires. Điều đó tạo thành lớp cơ sở trừu tượng. Sau đó, bạn có thể đặt cài đặt mặc định của bạn trong lớp khác và kế thừa từ đó:

#!/usr/bin/env perl 

use 5.014; 

package AbstractClass; 

use Moose::Role; 

requires 'my_virtual_method_this'; 
requires 'my_virtual_method_that'; 

package DefaultImpl; 

use Moose; 
with 'AbstractClass'; 

sub my_virtual_method_this { 
    say 'this'; 
} 

sub my_virtual_method_that { 
    say 'that' 
} 

package MyImpl; 

use Moose; 
extends 'DefaultImpl'; 
with 'AbstractClass'; 

override my_virtual_method_that => sub { 
    super; 
    say '... and the other'; 
}; 

package main; 

my $x = MyImpl->new; 

$x->my_virtual_method_this; 
$x->my_virtual_method_that; 

Nếu bạn muốn cung cấp triển khai mặc định cho chỉ một vài phương pháp xác định trong vai trò, loại bỏ các requires từ DefaultImpl.

Output:

$ ./zpx.pl 
this 
that 
... and the other
+1

Tôi nghĩ đây là một công việc tốt. Nó không "cảm thấy sạch sẽ", nhưng tôi sẽ gửi một danh sách mong muốn tăng cường cho việc này. Cảm ơn bạn vì câu trả lời này. – Joel