2011-02-03 59 views
5

Nếu tôi thêm một phương thức meta vào một lớp, tôi mong đợi nó sẽ hiển thị trong Class.metaClass.metaMethods. Nhưng điều này có vẻ không phải là trường hợp. Đặc biệt, nếu tôi làm điều này:Sự khác nhau giữa metaClass.methods và metaClass.metaMethods là gì?

class Example { 
    def realFoo() { "foo" } 

} 
Example.metaClass.metaFoo = { -> "foo" } 

def reals = Example.metaClass.methods*.name.grep{it.contains("Foo")} 
def metas = Example.metaClass.metaMethods*.name.grep{it.contains("Foo")} 

println "reals = $reals, metas = $metas" 

Tôi mong chờ kết quả của reals = [realFoo], metas = [metaFoo], nhưng tôi thực sự nhận được reals = [realFoo, metaFoo], metas = [].

Dường như các phương pháp meta mới được lưu trữ trong phương thức chứ không phải metaMethods. Vì vậy, sự khác biệt giữa metaClass.methodsmetaClass.metaMethods là gì?

Trả lời

6

MetaMethods chứa các phương thức được Groovy trang trí trên lớp, nhưng không thực sự là một phần trực tiếp của lớp hoặc cấu trúc thừa kế của nó hoặc đã được chèn thủ công vào lớp thông qua metaClass.

Chúng được xác định trong lớp DefaultGroovyMethods.

Tùy thuộc vào loại đối tượng bạn đang instantiating, nó chủ yếu là lặp như mỗi, thu thập, tìm vv

sửa đổi này để mã của bạn cho thấy các phương pháp mà là meta duy nhất, "thật" mà thôi, và chia sẻ:

class Example { 
    def realFoo() { "foo" } 

} 
Example.metaClass.metaFoo = { -> "foo" } 

def reals = Example.metaClass.methods.name.sort().unique() 
def metas = Example.metaClass.metaMethods.name.sort().unique() 

def metaOnly = metas - reals 
def realOnly = reals - metas 
def shared = reals.findAll { metas.contains(it) } 

println """ 
metaOnly = $metaOnly 
realOnly = $realOnly 
shared = $shared 
""" 

Kết quả:

metaOnly = [addShutdownHook, any, asBoolean, asType, collect, dump, each, eachWithIndex, every, find, findAll, findIndexOf, findIndexValues, findLastIndexOf, findResult, getAt, getMetaPropertyValues, getProperties, grep, hasProperty, identity, inject, inspect, is, isCase, iterator, metaClass, print, printf, println, putAt, respondsTo, sleep, split, sprintf, use, with] 
realOnly = [equals, getClass, getProperty, hashCode, metaFoo, notify, notifyAll, realFoo, setProperty, wait] 
shared = [getMetaClass, invokeMethod, setMetaClass, toString] 

Tất cả các metaOnly và phương pháp chia sẻ là trong DefaultGroovyMethods. Tất cả các phương thức "thực" là trên chính lớp đó, hoặc trên lớp cha của nó (Object trong trường hợp này), cộng với một vài thứ groovy liên quan trực tiếp đến metaClass để lấy/đặt metaClass cũng như getProperty/setProperty và invokeMethod cho phép bạn ghi đè hành vi của phương thức.

Nếu bạn muốn tìm kiếm thông qua tất cả các phương pháp để xem những gì tồn tại, tôi sử dụng một cái gì đó như thế này:

def allMethods = (Example.metaClass.methods + Example.metaClass.metaMethods).name.sort().unique() 
Các vấn đề liên quan