How can I subclass Perl 6 IO :: Handle?

How will I subclass IO :: Handle? For example, I want to be able to "autoflush", causing a flash after each say :

 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"; 

But it seems MyIO is never called.

I suppose I can wrap a word to produce an effect, but I'm more interested in the technique of simple subclasses to override any behavior. But having said that, if there is a more Perly 6 way that design intends to use for people.

So, some questions:

+5
source share
1 answer

Reblessing is sooo 90 :-)

Why not use role-playing composition to achieve your goal?

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

Basically, a new dynamic $*OUT based on the existing $*OUT , but with a new mixed say method.

To answer your questions, as well as I can:

  • rebempting is considered something internal that you most likely don't want to do
  • many built-in classes are optimized for speed without using the standard way to create objects. This sorting makes it difficult to subclass them. In some cases, custom code reverts to standard ways of creating objects, making these classes subclassed after all (for example, Date ).
  • In general, I would say that a low-level game is not recommended, as there are still internal refactories to speed things up, which could break your code if you play too little.

Since say internally uses print , it would be better to actually mix your own print method:

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

This has the added benefit of no longer having to say as a method, because the sub version of say will dynamically change the changed $*OUT .

+10
source

Source: https://habr.com/ru/post/1269701/


All Articles