プロパティとフィールドとメソッド

  • オブジェクトインスタンスのクラス名
    • obj.class.name
  • オブジェクトのプロパティ/メソッド/フィールド一覧
    • obj.properties
    • obj.class.methods.name
    • obj.class.fields.name
  • オブジェクトの文字列表現
    • obj.dump()

Pythonではクラスの変数もメソッドも全て属性(オブジェクト)で区別はないが、Groovyではプロパティ、フィールド、メソッドが明確に分かれている模様。

class Foo {
  def foo() {}
  def bar() { println this.class.methods[14].class }
}
new Foo().bar()

//実行結果
class java.lang.reflect.Method


結局、メソッドは、java.lang.reflect.Methodであり、クロージャは、org.codehaus.groovy.runtime.MethodClosureであることが分かった。一応メソッドもオブジェクトとして取得可能。「.」でアクセスできるのはプロパティとフィールドだけで、メソッドは恐らく不可能。「.&」でメソッドをアクセスするとクロージャとして取得可能。


メソッドをドットでアクセスできるようにするとプロパティと区別が付かないから、メソッドに直でアクセスできないのだろうか?「メソッド=プロパティ」として値としてクロージャを持っているとすれば問題ないような気がするけど、もっと深い問題はあるのだと思う。


そもそもJavaと互換性を持つというのはかなりの制限だとは思うが、もちろんかなりのメリットはあると思う。Groovyは互換性があることが一番の売りだというイメージあるので無理だと思うが、PyPyであればJVMコードにも変換できるので、基本的に互換性を持たせようとすると良い言語ができないのではないだろうか?昔のC++ではないが、とりあえずGroovyをBetter Javaとして使用するというのは良いかもしれない。


おまけ:

class Foo {
  aaa            // 何も指定しないとエラー
  final prop1
  static prop2
  int prop3
  def prop4
  public fld1
  protected fld2
  private fld3
  def prop5 = {}
  public fld4 = {}
  protected fld5 = {}
  private fld6 = {}
  def meth1() {}
  public meth2() {}
  protected meth3() {}
  private meth4() {}
}
def f = new Foo()
println f.properties
println f.class.methods.name
println f.class.fields.name

クラスメンバのプロパティ、フィールド、メソッドの区別のルールは以下の通り

  • public、protected、privateを指定するとフィールド(ただしメソッドは除く)
  • defを指定するとプロパティ
  • 何も指定しないとエラー
  • final、staticは区別に影響を与えない
  • int、Stringなどの型の指定は区別に影響を与えない
  • 値がクロージャの場合も区別に影響を与えない
  • メソッド(xxx meth() {}の形式)であれば、def、public、protected、privateの指定には関係なくメソッドとなる