2017-07-11 18 views
5

Làm cách nào để phân lớp IO :: Xử lý? Ví dụ, tôi muốn để có thể "autoflush" bằng cách gọi tuôn ra sau mỗi say:Làm thế nào tôi có thể phân lớp IO của Perl 6 :: Xử lý?

class MyIO is IO::Handle { 
    multi method say(MyIO:D: **@text --> True) { 
     nextsame; 
     $*ERR.say: "Flushing\n"; 
     self.flush; 
     } 
    }; 

Metamodel::Primitives.rebless: $*OUT, MyIO; 
put $*OUT.^name; 

$*OUT.say: "This is standard out"; 

Nhưng, dường như MyIO không bao giờ được gọi.

Tôi hình dung rằng tôi có thể bọc nói để tạo hiệu ứng, nhưng tôi quan tâm hơn đến kỹ thuật của các lớp con đơn giản để ghi đè lên một số hành vi. Nhưng, có nói rằng, nếu có một cách Perly 6 hơn là thiết kế dự định cho mọi người sử dụng.

Vì vậy, một số câu hỏi:

  • Liệu Perl 6 actaully chăm sóc mà tôi reblessed nó? Làm cách nào để tìm kiếm các tên phương thức có thể bỏ qua?

  • Các lớp dựng sẵn có đặc biệt chống lại các kỹ thuật OO tiêu chuẩn do phép thuật và NQPness của chúng không?

  • Có phải Perl 6 không khuyến khích mức độ khó xử lý thấp, chẳng hạn như mở lại $ * OUT trên bộ mô tả tệp? (Như trong Does changing Perl 6's $*OUT change standard output for child processes?)

+0

Một chút về tương lai trước: ngôn ngữ 6.d sẽ có các phương pháp cụ thể trên IO :: Xử lý bạn có thể ghi đè trong các lớp con của bạn để ảnh hưởng * tất cả * ghi/đọc. Các tên làm việc hiện tại là '.write-internal',' .read-internal' và '.eof-internal' mặc dù tên chưa được bikeshedded và specced. Một bản xem trước của việc sử dụng chúng có thể được nhìn thấy trong [impl hiện tại. của IO :: Pipe] (https: // github.com/rakudo/rakudo/blob/58900e7ba8ad31d905968d950bd9066a239320f5/src/core/IO/Pipe.pm # L25-L51) –

+2

Cũng lưu ý rằng ['nextsame' không trả lại cho người gọi] (https://rakudo.party/ post/Perl6-Nhưng-Heres-My-Dispatch-So-Callwith-Có lẽ). –

+1

nếu bạn chạy '.perl.say với $ * OUT.^Find_method (" say "). Ứng cử viên' bạn có thể thấy rằng ứng cử viên của bạn thực sự xuất hiện. nó không đủ cụ thể, tức là các ứng cử viên '$ text' thắng ứng cử viên' ** @ args' của bạn. – timotimo

Trả lời

10

Reblessing là sooo 90 :-)

Tại sao không sử dụng phần vai trò để đạt được mục tiêu của bạn?

role MyWay { 
    method say(|) { 
     note "whee"; 
     nextsame 
    } 
} 
my $*OUT = PROCESS::<$OUT> but MyWay; 
$*OUT.say("foo") # whee\nfoo 

này về cơ bản sẽ tạo ra một động lực mới $*OUT dựa trên $*OUT hiện nhưng với một phương pháp mới say trộn lẫn trong

Để trả lời câu hỏi của bạn cũng như tôi có thể:.

  • reblessing là coi nội dung nào đó mà bạn rất có thể không muốn làm
  • nhiều lớp dựng sẵn được tối ưu hóa cho tốc độ bằng cách không sử dụng cách tạo tiêu chuẩn chuẩn. Phân loại này làm cho nó khó phân lớp chúng. Trong một số trường hợp, mã đặc biệt hoàn nguyên theo cách tạo đối tượng tiêu chuẩn, làm cho các lớp này có thể phân lớp sau tất cả (như Date).
  • nói chung tôi sẽ nói mức độ thấp không quan trọng là không được thông báo vì vẫn còn các bộ lọc nội bộ đang được tiến hành để làm cho mọi việc nhanh hơn, điều này có thể phá vỡ mã của bạn nếu bạn không sử dụng quá thấp.

Kể từ say nội bộ sử dụng print, nó sẽ là tốt hơn để thực sự trộn trong phương pháp print riêng bạn:

role MyWay { 
    method print(|) { 
     note "whee"; 
     nextsame 
    } 
} 
my $*OUT = PROCESS::<$OUT> but MyWay; 
say "foo"; # whee\nfoo 

này có lợi ích bổ sung không còn cần phải gọi say như một phương pháp, bởi vì phiên bản phụ của say sẽ tự động thay đổi $*OUT.

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