守破離さんのところで書いてたことをGroovyのソースコード上検証してみた。
groovy-1.6-beta-1/src/main/groovy/lang/MetaClassImpl.java
public Object getProperty(Class sender, Object object, String name, boolean useSuper, boolean fromInsideClass) { : //---------------------------------------------------------------------- // special cases //---------------------------------------------------------------------- } else if (object instanceof Collection) { return DefaultGroovyMethods.getAt((Collection) object, name);
と、getPropertyについてCollectionのときを特別扱いしていて、DefaultGroovyMethods.getAt(Collection,String)を呼び出しておる。
んでさらに、list.getAt(prop)の実体は
groovy-1.6-beta-1/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
public static List getAt(Collection coll, String property) { List answer = new ArrayList(coll.size()); for (Iterator iter = coll.iterator(); iter.hasNext();) { Object item = iter.next(); Object value; try { value = InvokerHelper.getProperty(item, property); } catch (MissingPropertyExceptionNoStack mpe) { String causeString = new MissingPropertyException(mpe.getProperty(), mpe.getType()).toString(); throw new MissingPropertyException("Exception evaluating property '" + property + "' for " + coll.getClass().getName() + ", Reason: " + causeString); } answer.add(value); } return answer; }
というもので、もともとここはカテゴリを使ってGDKメソッドとして定義されているgetAtであります。
上ではぐるぐるfor文を回してArrayListを返しておるわい。ちなみにgetAtだから、
class X { def a } assert [3,4] == [new X(a:3), new X(a:4)].a assert [3,4] == [new X(a:3), new X(a:4)]['a']
でもある。後者は変な感じ。
あと、たとえばSetとかでもArrayListに変換されちゃうんだねえ。
class X { def a } x = [new X(a:3), new X(a:4)] as Set assert x.a == [4, 3] assert x.a instanceof java.util.ArrayList
ま、いいですかね。
メモとして。