1

注:これは本当に Jython 信奉者への質問ですが、言語の設計上の難しさを浮き彫りにしているようです

私がこのようにsthgをしたら

class XTreeModel( DefaultTreeModel ):  
  def fireTreeNodesInserted( self, source, path, child_indices, children ):
    print "fire nodes inserted"
    super( XTreeModel, self ).fireTreeNodesInserted( source, path, child_indices, children )

無限再帰を取得します。これに初めて出会ったとき、私は非常に戸惑いました。なぜコードが Java スーパークラス (ベースクラス) メソッドを呼び出せず、代わりに自分自身を再度呼び出すのか (!) はまだわかりません。これを防ぐために私は行きます

class XTreeModel( DefaultTreeModel ):  
  def fireTreeNodesInserted( self, source, path, child_indices, children ):
    print "fire nodes inserted"
    self.super__fireTreeNodesInserted( source, path, child_indices, children )

...そして、Jython を使い始めてから、これらの Java ベースクラス呼び出しの「super__XXX」メソッドは、実際には Jython インタープリターによって自発的に作成され、サブクラス化された Jython クラスで Java メソッドをオーバーライドした場合にのみ作成されることを学びました。 Java クラス (上記)。ここまでは問題ありませんが、スーパークラス (基底クラス) が Java クラスであるかどうかがわからない場合はどうすればよいでしょうか? 私は最終的に次のユーティリティメソッドを開発しました:

def get_super_method( caller, code_class ):
  stack_1 = inspect.stack()[ 1 ]
  func_name = stack_1[ 3 ]
  # unfortunately this will return code_class.func_name as standard if code_class is a derived from a Java class with method func_name
  supposed_baseclass_method = getattr( super( code_class, caller ), func_name )
  for baseclass in caller.__class__.__base__.__mro__:
    if "org.python.proxies" in str( baseclass ):
      # ... this means we have reached down as low as a Java "proxy" class without yet encountering a class with a method 'func_name',
      # which means that we must return the super__XXX version
      break
    # confusingly, even if you go caller.__class__.__base__.__mro__ this still shows all the classes for caller, including its highest class! 
    if baseclass == code_class:
      continue
    if func_name in baseclass.__dict__:
      # ... a method with the right name exists in a baseclass...
      return supposed_baseclass_method 
  java_baseclass_method = getattr( caller, "super__%s" % func_name )
  return java_baseclass_method

たとえば、次のように呼び出します。

class XTreeModel( DefaultTreeModel ):  
  def fireTreeNodesInserted( self, source, path, child_indices, children ):
    print "X fire nodes inserted"
    get_super_method( self, XTreeModel )(source, path, child_indices, children )

class XXTreeModel( XTreeModel ):  
  def fireTreeNodesInserted( self, source, path, child_indices, children ):
    print "XX fire nodes inserted"
    get_super_method( self, XXTreeModel )(source, path, child_indices, children )

ここで、XXTreeModel の get_super_method は super( XXTreeModel, self ) を返します... 一方、XTreeModel の get_super_method は self.super__fireTreeNodesInserted を返します... get_super_method に渡された code_class を見て、これは、super__XXX バージョンを返すことを意味します。ええと、いいえ、それはもう少し複雑です:

class XTreeModel( DefaultTreeModel ):  
  def do_some_stuff( self ):
    print "do stuff"

class XXTreeModel( XTreeModel ):  
  def fireTreeNodesInserted( self, source, path, child_indices, children ):
    print "XX fire nodes inserted"
    get_super_method( self, XXTreeModel )(source, path, child_indices, children )

この例では、XXTreeModel はその基本クラスとして Jython クラスを持っていますが、この基本クラス (XTreeModel) は目的のメソッドをオーバーライドしません。したがって、実際には XXTreeModel の get_super_method() は super__ fireTreeNodesInserted を返す必要があります。このユーティリティ メソッドは問題を解決しているようです。基底クラスがどのタイプのクラスであるか、それが Java メソッドをオーバーライドするかどうかなどを知る必要はありません。とにかく、この曲がりくねった手順が必要かどうかを知りたかったのですが、グーグル「jython super」などは、10年前から「super__メソッドの使用は非推奨」などのバグエントリを作成しました。

スーパークラスメソッドのこの呼び出しを達成するためのより良い方法はありますか? (クラスを下に移動するときに) 求められるメソッドを持つ最初のベースクラスは実際には Java クラスですか?

4

1 に答える 1