uehaj's blog

Grな日々 - GroovyとかGrailsとかElmとかRustとかHaskellとかReactとかFregeとかJavaとか -

コレクションに対するプロパティ参照はコレクション要素のプロパティ参照結果をリストにしたものとして扱われる

守破離さんのところで書いてたことを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

ま、いいですかね。
メモとして。