groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dinko Srkoč <dinko.sr...@gmail.com>
Subject Re: Metaclass programming and Groovy (2.3.7) traits
Date Wed, 22 Jul 2015 09:12:58 GMT
On 21 July 2015 at 21:11, Sean LeBlanc <sean.leblanc@icd-tech.com> wrote:
> Thanks. I should have mentioned that I would have used that approach, except
> that I wasn't able to figure out how to then set that resulting object to
> the object I want (which is strongly typed in prod code).

It is true that when using `withTraits()` your new object is no longer
of the original type. But I was under the impression that this is for
tests, not production. Also, even though the object's class is not C
any more, it still implements T, so instead of:

  C c = new C().withTraits T2

you could use

  T c = new C().withTraits T2

to see the type checker happy.

>
> Is there any chance this metaclass behavior is related to this bug? We also
> just ran into this one recently, as we started to use more interfaces to
> enforce some behaviors we want concrete classes to have.
>
> https://issues.apache.org/jira/browse/GROOVY-3493
>

There are certainly similarities, and traits are implemented as
interfaces + helper classes, so I guess there is a chance.

Cheers,
Dinko

>
>
> On 7/20/15 2:30 AM, Dinko Srkoč wrote:
>
>> On 17 July 2015 at 19:23, Sean LeBlanc <sean.leblanc@icd-tech.com> wrote:
>>>
>>> I'm trying to figure out the recommended way to write unit tests for
>>> classes
>>> that have methods implemented as traits that need to be overwritten with
>>> metaclass programming.
>>
>> If what you needed is just overriding trait's methods, you could do it
>> with another trait, without resorting to metaclass fiddling:
>>
>>    trait T {
>>        def speak() {
>>            println "trait version"
>>        }
>>    }
>>
>>    class C implements T {}
>>
>>    trait T2 {
>>        def speak() {
>>            println "another trait"
>>        }
>>    }
>>
>>    def c = new C().withTraits T2
>>    c.speak() // prints "another trait"
>>
>> Cheers,
>> Dinko
>>
>>>
>>> What I've noticed is that using an instance of the class doesn't seem to
>>> work, nor does using the class itself. (Commented out below)
>>>
>>> It seems that setting is on the trait itself does work, however, this
>>> must
>>> be done before the first time the implementing class is created, or else
>>> setting the metaClass to null on the implementing class is required (also
>>> commented out below)?
>>>
>>>
>>> Is there a better way to do this?
>>>
>>>
>>> trait T {
>>>    def speak() {
>>>       println "trait version"
>>>    }
>>> }
>>>
>>> class C implements T {
>>> }
>>>
>>> def c = new C()
>>> //c.metaClass.speak = { -> println "meta" }
>>> //C.metaClass.speak = { -> println "meta" }
>>>
>>> c.speak()
>>> //C.metaClass = null
>>>
>>> T.metaClass.speak = { println "meta class version" }
>>> def c2 = new C()
>>> c2.speak()
>
>

Mime
View raw message