フレームワーク (8) - サブクラスでのメソッドのオーバーライドを禁止する

フレームワーク (8) - サブクラスでのメソッドのオーバーライドを禁止する #

C::M::App は、CGI::Application と同様、自分のクラスから継承されることを想定している

 package MyClass;
 use basee 'CGI::Minimal::App';
 
 1;

んだが、一部メソッドは子クラスでのオーバーライド前提だし、一部メソッドはオーバーライドされたくないし、ということで、思案。他の言語みたいに attribute :final とか用意されてると

 sub cannot_override :final {
 }

とかするだけだし、そういうことを行うモジュール Attribute::Final もあるんだが、外部モジュール使うほどでもないし、attribute で実装しなくてもよかろう

 # 子クラスの時だけ実行
 unless ( ref $self eq __PACKAGE__ ) {
   for my $method (@all_methods) {
     next if .... ; # 親クラスのメソッドだったら何もしない
 
     die 'You can NOT OVERRIDE method'
       if ( grep {$_ eq $method} @not_override_methods );
   }
 }

まずは基本ということで、Class::Inspector 使ってみる

 # Check methods that cannot override in Sub-Class
 unless ( ref $self eq __PACKAGE__ ) {
   my @not_override_methods = qw(
                                 new run
                                 _tt_obj _setup_http_headers _lvalue_method
                                );
   for my $method ( @{Class::Inspector->methods(ref $self, 'expanded') || [[]]} ) {
     next if $method->[1] eq __PACKAGE__;
     die 'You can NOT OVERRIDE method ',__PACKAGE__,'::',$method->[2],' in ',$method->[1]
       if ( grep {$_ eq $method->[2]} @not_override_methods );
   }
 }

続いて、Class::Inspector はコアモジュールではないので、使わない版

 # Check methods that cannot override in Sub-Class
 unless ( ref $self eq __PACKAGE__ ) {
   my @not_override_methods = qw(
                                 new run
                                 _tt_obj _setup_http_headers _lvalue_method
                                );
   {
      no strict 'refs';
      for my $method ( keys %{ref($self).'::'} ) {
        next unless defined &{ref($self).'::'.$method};
        die 'You can NOT OVERRIDE method ',__PACKAGE__,'::',$method,' in ',ref($self)
          if ( grep {$_ eq $method} @not_override_methods );
      }
   }
 }

タイムリーなことに、「どう書く?org 」で「メソッド名一覧の表示 」がお題になっているので、良さげな回答がでてきたらマネさせてもらおう

で、この実装だとコンストラクタ生成後にチェックするので、use した時点でチェクする方法考えた方がいいのかなぁ、とちょっと思った。new のしょっぱなにやっとけば同じかな

See Also

Copyright © 髭。/ Hugo + hugo-book