You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@groovy.apache.org by frenchy48 <ba...@in2p3.fr> on 2016/03/27 17:38:57 UTC

changing dynamically the name of classes in a source code

Before asking a question I'l have first to explain WHY this question.  

I have been writing a book about programming (for beginners)  

For the labs I use  a small subset of Groovy  
now my labs are slightly boring so I decided to write a small graphical
library to facilitate the design of funnier experiments.  

This small library is built around about 20 groovy classes and provides a
simple framework to do some graphical programming.  

The people going to use this codes are not english speaking people.  
But it's not a big problem when limiting the use of english to some keywords
(for, while, if,...) or a limited number of types such as List or Map.  

But if I introduce more classes it may be a problem.  

So I started thinking about internationalisation of code.  

For my limited number of classes I implemented a "methodMissing" feature
that implements a translation of method names.  
it works (though error handling is not perfect and can be confusing)  

Now I was wondering if I could translate the name of this library's classes
at runtime.
(there are already languages such as Scratch which are translated in the
user's language -including keywords ... but I don't need to go that far-)  

And here are my questions : how to do that and is it worth the trouble?  

I toyed with the idea of using ASTTransformation but I really don't know how
to visit my class names and if I can change them at runtime.  
Since the programming features are limited the students are not going to use
the constructors of the classes (there are only factories).
So the only places where the class names should be changed is when declaring
variables or parameter types.  
(I could sed the source code but I would rather not)  

so is this transformation doable? when? (parsing or semantic?) how?
(performance is not an issue and  students program through the
groovyconsole)  

(for sure error handling is going to be even more problematic when the user
sees a message pertaining to a class which is "under the hood")  

Any advice?  

thanks  




-----
member of Grumpy Old Programmers
--
View this message in context: http://groovy.329449.n5.nabble.com/changing-dynamically-the-name-of-classes-in-a-source-code-tp5732080.html
Sent from the Groovy Users mailing list archive at Nabble.com.

Re: changing dynamically the name of classes in a source code

Posted by frenchy48 <ba...@in2p3.fr>.
to aseem: I willl publish my codes as open source
(because I think it is important to teach in your own language
BTW: arabic is a problem to me because I no not know how students could
handle bidirectional code text)  

in the meantime here is the subclass of groovyConsole:  


I have also a trait that translates the missing methods
and a 'ScrountchScript' class that redirects Factory methods as just plain
functions

hope this helps

regards




-----
member of Grumpy Old Programmers
--
View this message in context: http://groovy.329449.n5.nabble.com/changing-dynamically-the-name-of-classes-in-a-source-code-tp5732080p5732125.html
Sent from the Groovy Users mailing list archive at Nabble.com.

Re: changing dynamically the name of classes in a source code

Posted by Aseem Bansal <as...@gmail.com>.
Hi frenchy48

Can you share what you did? Did you subclass groovyConsole and then gave
that subclass to your students to be used as groovyConsole?

On Tue, Mar 29, 2016 at 7:47 PM, frenchy48 <ba...@in2p3.fr> wrote:

> answer found
> Groovy is fantastic!
> Since I use the groovyConsole for my teaching scripts
> I created a subclass of groovy console
> then modified the CompilerConfiguration to accept an importCustomizer that
> aliases import!
> fun!
>
>
>
> -----
> member of Grumpy Old Programmers
> --
> View this message in context:
> http://groovy.329449.n5.nabble.com/changing-dynamically-the-name-of-classes-in-a-source-code-tp5732080p5732103.html
> Sent from the Groovy Users mailing list archive at Nabble.com.
>

Re: changing dynamically the name of classes in a source code

Posted by frenchy48 <ba...@in2p3.fr>.
answer found
Groovy is fantastic!
Since I use the groovyConsole for my teaching scripts
I created a subclass of groovy console
then modified the CompilerConfiguration to accept an importCustomizer that
aliases import!
fun!



-----
member of Grumpy Old Programmers
--
View this message in context: http://groovy.329449.n5.nabble.com/changing-dynamically-the-name-of-classes-in-a-source-code-tp5732080p5732103.html
Sent from the Groovy Users mailing list archive at Nabble.com.

Re: Proxying how to?!?

Posted by OC <oc...@ocs.cz>.
Jochen,

thank you very much for quick and, as always, very knowledgeable response!

On 30. 3. 2016, at 17:12, Jochen Theodorou <bl...@gmx.org> wrote:
> There are multiple ways to "solve" the problem, but I am afraid, they will all look like workarounds to you... The traditional Java way would be:
> interface InterfaceForAnyClassOfMine {
>  def getName()
> }
...

Well of course, but the problem is with 3rd-party classes, which do not implement such an interface (and they might be even final, which prevents also all possible subclassing tricks and actually _forces_ proxying).

And generally, it is 3rd-party classes one needs to proxy most time; one's own classes (which I use here to quickly elucidate the gist of the problem) allow lots of other ways solve anything which might proxy be needed for.

> Then of course you would not use AnyClassOfMine as base, but InterfaceForAnyClassOfMine. You can make this a little bit more easy with @Delegate:
> class DumbProxy {
>  @Delegate InterfaceForAnyClassOfMine server
> }

I do not like this approach, for it does not cover dynamics of the server -- far as I understand it properly, that is.

If the proxy forwards instead, i.e.,

===
class DumbProxy { def server; def methodMissing(name,args) { server."$name"(*args) } }
===

it covers even e.g., any functionality which has been added to server through its metaclass at runtime.

On the other hand, I grant @Delegate one definite advantage (its methods would work when called from Java, which methodMissing can't ever do, I am afraid), and one potential -- it might be considerably faster[*].

> Using runtime traits I would come up with this version:
> class AnyClassOfMine { def name }
> trait DumbProxy {}
> def objects=[new AnyClassOfMine(name:"Proxied") as DumbProxy]
> for (DumbProxy o in objects) println "got $o.name"

This seems very interesting! I simply _must_ clean up my quagmire of ASTTs so that they work with traits! (While I completely appreciate the strong reasons which led you to sort-of deprecate ASTTs with traits, I must admit for me it was _very_ sad decision, which still, even today, prevents me to use traits and forces me to stick with 3.8 :( )

> I think the basic problem is that you have no multiple inheritance in Java and only an inconsitent fraction of it in Groovy.

Sort of. Myself, I would rather say the problem is basically in the Java terrible howler of making static class/interface relationships overimportant.

ObjC does not have MI either, but it can be easily _simulated_ in there using message forwarding. In Groovy (even in plain Java, with some boilerplate code essentially doing by hand what your @Delegate ASTT does), it would work just as well, only if it were possible to typecast a DumbProxy instance to AnyClassOfMine. There is no harm in it, for any method callable of AnyClassOfMine is also callable of DumbProxy; alas, Java atrifically (and dumbly) closes that door by the very “Cannot cast object” exception.

> So on the JVM I cannot make a class that implements a class AnyClassOfMine and DumbProxy at the same time.

That is actually not needed at all. All we need is that the JVM calls AnyClassOfMine methods on DumbProxy object. Which is problematic in pure Java (I understand one needs reflexion for that, can be done, but is beyond ugly), but no problem at all in Groovy.

Groovy does allow that, and it works excellectly, if we stick with “def”. The problem occurs when there is an existing API which not only _uses_ an instance of AnyClassOfMine, but also _declares it_ as one. E.g.,

def gimmeObject { return flag?objectOfClassX:proxyToClassX } //[1]

works as-is without any glitch. Contrariwise

ClassX gimmeObject { return flag?objectOfClassX:proxyToClassX }

does not, only due to the blasted “Cannot cast object” exception; if it was not for that thing, it would work just as well as [1] above.

> I can do such things with interfaces though. This again forces people to split their classes in interfaces and implementations, both being first class citizens. Objective C is much more flexible here.

I don't really think so. First, ObjC is actually more rigid in many places (e.g., it _forces_ you to split _any_ class to interface and implementation, willy-nilly :)), but the one (and in this particular context I belive _only_ important) difference is that it freely lets you cast anything to anything. The compiler, of course, behaves accordingly, trusting you you had a good reason to do that typecast.

Of course, if you typecast, say, a Map to a String, the program would crash as soon as the real Map gets first String's message it does not implement; but there's no potential problem in that -- nobody sane would do such a typecast (and whomever would, serves him right).

On the other hand, it allows proxying. And more.

> But it means I cannot apply the same concept to the JVM world... not if I want to stay with the Java class model.

That all said, I am afraid this still applies -- far as I understand, you not only can't make “a class that implements a class AnyClassOfMine and DumbProxy at the same time” (which is not needed), but you also cannot make a class which

(a) would implement DumbProxy; any method called on its instance would be interpreted normally
(b) at the same moment, would _look to_ the compiler _like_ AnyClassOfMine in the sense it would call AnyClassOfMine's methods on its instances (and use AnyClassOfMine to resolve calls which depend on argument type etc.)

Note that (b) would not _change_ the class anyhow; it would still stay a true-blue DumbProxy. The only difference is that compiler would use it _as it were_ an AnyClassOfMine (which it is not).

> ... But once you have two super classes you are lost... especially without the magic -forwardingTargetForSelector:(SEL)sel { return self.server; }

I believe _this_ one magic you could implement in Groovy dispatcher, if you wanted, and pretty easily at that. It is nothing but a quick-and-fast shortcut to “methodMissing(name,args) { target."$name"(*args) }”, which only forwards and does not pre-/post-process the method, nothing else. Its purpose is to make it easier for programmer and faster runtime, but the functionality is precisely the same[**].

Thanks and all the best,
OC

[*] On the other hand, the speed difference should not be that big if the forwarding is done right, that is, at first forward the proxy itself installs the stub through its own metaclass. Nevertheless, that's an optimization which works nicely (most time), but is not relevant to the current debate.

[**] Actually in Groovy you would probably have to solve properties separately; ObjC has properties too, but defines them solely through their accessors, which, I believe, is easier -- at least, you don't need separate “methodMissing” and “propertyMissing” (twice) etc., for “methodMissing” catches property accessors just as well as all other methods. But this, too, is completely irrelevant to the current discussion :)


Re: static propertyMissing in an interface

Posted by OC <oc...@ocs.cz>.
Jochen,

On 3. 4. 2016, at 22:29, Jochen Theodorou <bl...@gmx.org> wrote:

> On 03.04.2016 17:33, OC wrote:
> [...]
>> ===
>> 6 /tmp> <q.groovy
>> class q {
>>  static main(av) {
>>    ExpandoMetaClass.enableGlobally()
>>    Root.metaClass.static.propertyMissing={ name ->
>>      String getter="get${name.capitalize()}"
>>      def body={-> "<$name in $delegate>" }
>>      delegate.metaClass.static."$getter"=body
>>      body.call() // same problem with body(); delegate."$getter"() would work though
>>    }
>>    println "- ${Root.weird}"
>>  }
>> }
>> interface Root {}
>> 7 /tmp> groovy q.groovy
>> Caught: groovy.lang.MissingMethodException: No signature of method: java.io.StringWriter.capitalize() is applicable for argument types: () values: []
>> groovy.lang.MissingMethodException: No signature of method: java.io.StringWriter.capitalize() is applicable for argument types: () values: []
>> 	at q$_main_closure1.doCall(q.groovy:5)
>> 	at q.main(q.groovy:10)
>> 8 /tmp>
> 
> so I misunderstood... it was not, that somehow body was not recognized as closure or such, it is that the execution of  code inside fails. capitalize() is a method on CharSequence, StringWriter is no CharSequence, so the call fails. Did you add such a method yourself? if not, you need to convert to String first.

Convert what?

I call the capitalize method only once, on the name argument of the propertyMissing closure. That is/should be always a String, should it not? Or is there a valid case where this argument would be something else?

Besides the problem disappears if the "body()" or "body.call()" call gets replaced by "delegate."$getter"()", which is sort of weird, for delegate."$getter" actually contains the very body closure :-O

It looks like the way the body closure captures the name variable is... weird: it seems when body.call() is performed, the propertyMissing closure gets called again, this time with a StringWriter for "name", in a way which is completely obscure to me:

===
14 /tmp> <q.groovy      
class q {
 static main(av) {
   ExpandoMetaClass.enableGlobally()
   Root.metaClass.static.propertyMissing={ String name ->
     def body={-> "<$name in $delegate>" }
     body.call()
   }
   println "- ${Root.weird}"
 }
}
interface Root {}
15 /tmp> groovy q.groovy
Caught: groovy.lang.MissingMethodException: No signature of method: q$_main_closure1.doCall() is applicable for argument types: (java.io.StringWriter) values: [- <weird in ]
...
16 /tmp> 
===

Thank you very much and all the best,
OC


Re: static propertyMissing in an interface

Posted by Jochen Theodorou <bl...@gmx.org>.
On 03.04.2016 17:33, OC wrote:
[...]
> ===
> 6 /tmp> <q.groovy
> class q {
>   static main(av) {
>     ExpandoMetaClass.enableGlobally()
>     Root.metaClass.static.propertyMissing={ name ->
>       String getter="get${name.capitalize()}"
>       def body={-> "<$name in $delegate>" }
>       delegate.metaClass.static."$getter"=body
>       body.call() // same problem with body(); delegate."$getter"() would work though
>     }
>     println "- ${Root.weird}"
>   }
> }
> interface Root {}
> 7 /tmp> groovy q.groovy
> Caught: groovy.lang.MissingMethodException: No signature of method: java.io.StringWriter.capitalize() is applicable for argument types: () values: []
> groovy.lang.MissingMethodException: No signature of method: java.io.StringWriter.capitalize() is applicable for argument types: () values: []
> 	at q$_main_closure1.doCall(q.groovy:5)
> 	at q.main(q.groovy:10)
> 8 /tmp>

so I misunderstood... it was not, that somehow body was not recognized 
as closure or such, it is that the execution of  code inside fails. 
capitalize() is a method on CharSequence, StringWriter is no 
CharSequence, so the call fails. Did you add such a method yourself? if 
not, you need to convert to String first.

bye Jochen


Re: static propertyMissing in an interface

Posted by OC <oc...@ocs.cz>.
Jochen,

On 3. 4. 2016, at 7:23, Jochen Theodorou <bl...@gmx.org> wrote:

> On 01.04.2016 03:48, OC wrote:
>> playing with possibilities of the i/i pattern, I have found one can install a static property to an interface, and then use the property all right -- see a proof-of-concept below.
>> 
>> Since it might be used e.g. to create instances or to get a factory through public API based on interfaces (which would otherwise not be possible without exposing the implementation class), this is truly interesting.
>> 
>> The question is: can I rely on this rather arcane behaviour, that it will not be broken in future Groovy versions?
> 
> if you want to be really sure it will continue working it is best if you contribute a test case ;) But I see no plans to change that, especially with java8 being able to define static methods and thus static properties.

Thanks a lot!

> [...]
>>       def body={-> "<$name in $delegate>" }
>>       delegate.metaClass.static."$getter"=body
>>       delegate."$getter"() // I wonder why just "body()" does not work?!?
> 
> no idea why not... but you can always try body.call() instead.

Same as with body():

===
6 /tmp> <q.groovy 
class q {
 static main(av) {
   ExpandoMetaClass.enableGlobally()
   Root.metaClass.static.propertyMissing={ name ->
     String getter="get${name.capitalize()}"
     def body={-> "<$name in $delegate>" }
     delegate.metaClass.static."$getter"=body
     body.call() // same problem with body(); delegate."$getter"() would work though
   }
   println "- ${Root.weird}"
 }
}
interface Root {}
7 /tmp> groovy q.groovy
Caught: groovy.lang.MissingMethodException: No signature of method: java.io.StringWriter.capitalize() is applicable for argument types: () values: []
groovy.lang.MissingMethodException: No signature of method: java.io.StringWriter.capitalize() is applicable for argument types: () values: []
	at q$_main_closure1.doCall(q.groovy:5)
	at q.main(q.groovy:10)
8 /tmp> 
===

Thanks again and all the best,
OC


Re: static propertyMissing in an interface

Posted by Jochen Theodorou <bl...@gmx.org>.
On 01.04.2016 03:48, OC wrote:
> Hello there,
>
> playing with possibilities of the i/i pattern, I have found one can install a static property to an interface, and then use the property all right -- see a proof-of-concept below.
>
> Since it might be used e.g. to create instances or to get a factory through public API based on interfaces (which would otherwise not be possible without exposing the implementation class), this is truly interesting.
>
> The question is: can I rely on this rather arcane behaviour, that it will not be broken in future Groovy versions?

if you want to be really sure it will continue working it is best if you 
contribute a test case ;) But I see no plans to change that, especially 
with java8 being able to define static methods and thus static properties.

[...]
>        def body={-> "<$name in $delegate>" }
>        delegate.metaClass.static."$getter"=body
>        delegate."$getter"() // I wonder why just "body()" does not work?!?

no idea why not... but you can always try body.call() instead.

bye Jochen

static propertyMissing in an interface (was: interface/implementation patten)

Posted by OC <oc...@ocs.cz>.
Hello there,

playing with possibilities of the i/i pattern, I have found one can install a static property to an interface, and then use the property all right -- see a proof-of-concept below.

Since it might be used e.g. to create instances or to get a factory through public API based on interfaces (which would otherwise not be possible without exposing the implementation class), this is truly interesting.

The question is: can I rely on this rather arcane behaviour, that it will not be broken in future Groovy versions?

Thanks,
OC

===
78 /tmp> <q.groovy
class q {
  static main(av) {
    ExpandoMetaClass.enableGlobally()
    Root.metaClass.static.propertyMissing={ name ->
      String getter="get${name.capitalize()}"
      println "... PMISS($name) in $delegate, installing $getter()"
      def body={-> "<$name in $delegate>" }
      delegate.metaClass.static."$getter"=body
      delegate."$getter"() // I wonder why just "body()" does not work?!?
    }

    println "- ${Foo.staticPropertyOfInterfaceWow}"
    println "- ${Bar.itReallyWorks}"
    println "second time, they go directly without PMISS"
    println "- ${Foo.staticPropertyOfInterfaceWow}"
    println "- ${Bar.itReallyWorks}"
  }
}

interface Root {}
interface Foo extends Root {
}
interface Bar extends Foo {
}
79 /tmp> groovy q 
... PMISS(staticPropertyOfInterfaceWow) in interface Foo, installing getStaticPropertyOfInterfaceWow()
- <staticPropertyOfInterfaceWow in interface Foo>
... PMISS(itReallyWorks) in interface Bar, installing getItReallyWorks()
- <itReallyWorks in interface Bar>
second time, they go directly without PMISS
- <staticPropertyOfInterfaceWow in interface Foo>
- <itReallyWorks in interface Bar>
80 /tmp> 
===

Re: interface/implementation patten

Posted by OC <oc...@ocs.cz>.
Jochen,

On 30. 3. 2016, at 20:48, Jochen Theodorou <bl...@gmx.org> wrote:

> I am unhappy about the semantics of static methods in general in Java and that we copied most of it in Groovy...

You are telling me :) Hardly you can have missed my occassional bitter rants re static „methods“ :)

I sort of recall we debated ages ago whether there might be a way to turn them to real full-fledged class methods, properly inheritable with a real “this“ representing the receiver, not the implementor; but I am afraid the result of that conversation was that something like that would be somewhere at the edge betwixt “impossible” and “impractically difficult” :(

> extending that to interface is for me no good decision... but well...

I would be infinitely happier if those jokers in Sun have designed the thing properly (it's not just static “methods“, it's much more -- including the “Cannot cast object” exception howler of the other thread); but well, they did not, triple alas.

Anyway, far as static „methods“, with all their shortcomings, can be part of the class API, I am afraid the interface needs to be able to contain the things. After all, that's the purpose of the interface: to define the public API of the class; no less, no more. If the public API can contain those uglies, the interface should, too.

Or am I overlooking something of importance here?

> I guess it is up to you. I know of nothing in that area to make this less painful

OK, thanks; I guess I'll try to rig some kind of private preprocessor reading sources which would contain ObjC-like class directives, and generating the appropriate .groovy files with all the interfaces, implementations, factories etc. After all, ages ago the C preprocessor used to be implemented this very way, and it worked well.

It would complicate somewhat the incremental build on one side, and error reporting (more precisely, matching the reports to sources) on the other; but the problems should not be insurmountable, I guess -- I need to postprocess error reports anyway, since I use Xcode instead of Eclipse, and thus I have to squeeze the reports so that Xcode understands them. And the big advantage (against the ASTT approach) would be no problem with traits :)

Thanks again a very big lot and all the best,
OC


Re: interface/implementation patten

Posted by Jochen Theodorou <bl...@gmx.org>.
On 30.03.2016 18:59, OC wrote:
> Oh, by the way,
>
> On 30. 3. 2016, at 17:12, Jochen Theodorou <bl...@gmx.org> wrote:
>> This again forces people to split their classes in interfaces and implementations
>
> reminded me another question of mine. I actually want to embrace this pattern for a long time (after all, I am used to it from ObjC), but there are two problems:
>
> (a) interfaces cannot contain static methods
>
> I am afraid there would be no solution at all in Java-based world, or does Groovy bring some?

This require support through the JVM... and actually Java8 has that... 
But I think we do not support that yet. I am unhappy about the semantics 
of static methods in general in Java and that we copied most of it in 
Groovy... extending that to interface is for me no good decision... but 
well...

> (b) they force me to maintain two parallel hierarchies, like
>
> ===
> interface Foo {
>    def foo();
>    ...
> }
> class Foo_Implementation implements Foo {
>    def foo() { ... }
>    def myfoo() { ... }
>    ...
> }
> interface Bar implements Foo {
>    def bar();
>    ...
> }
> class Bar_Implementation extends Foo_Implementation implements Bar {
>    def bar() { ... }
>    ...
> }
> ===
>
> with a high danger of a mistake leading to inconsistence of these two hierarchies. Not speaking of the factory pattern to replace those pesky static methods, which would, alas, add a third hierarchy for factories; if I wanted to use interface/implementations for factories too, I get _four_ parallel hierarchies, which need to keep consistent! Quadruple ick.
>
> Is there some trick in Groovy which makes this task groovier (or at the very least reasonably manageable), or am I up to my own source preprocessor and/or ASTTs (which again would clash with traits :/ )?

I guess it is up to you. I know of nothing in that area to make this 
less painful

bye Jochen



RE: interface/implementation patten (was: Proxying how to?!?)

Posted by "Winnebeck, Jason" <Ja...@windstream.com>.
In Java 8+, interfaces can have static methods, and with default methods, you can simulate multiple inheritance. To be honest, I'm not sure how/if you can use this from Groovy -- if Groovy interface can define static or default methods. In the case of conflicts, Java forces you to override the shared method. From the override you can call one of the super class versions if you want.

public interface Foo {
	static String getFoo() {
		return "Foo";
	}

	default String foo() {
		return getFoo();
	}

	default String shared() {
		return foo();
	}
}

public interface Bar {
	default String bar() {
		return "Bar";
	}

	default String shared() {
		return bar();
	}
}

public class FooBar implements Foo, Bar {
	public static void main(String[] args) {
		FooBar fooBar = new FooBar();
		System.out.println(fooBar.foo());
		System.out.println(fooBar.bar());
		System.out.println(fooBar.shared());
	}

	@Override
	public String shared() {
		return Foo.super.shared();
	}
}

Jason

-----Original Message-----
From: OC [mailto:ocs@ocs.cz] 
Sent: Wednesday, March 30, 2016 12:59 PM
To: users@groovy.apache.org
Subject: interface/implementation patten (was: Proxying how to?!?)

Oh, by the way,

On 30. 3. 2016, at 17:12, Jochen Theodorou <bl...@gmx.org> wrote:
> This again forces people to split their classes in interfaces and implementations

reminded me another question of mine. I actually want to embrace this pattern for a long time (after all, I am used to it from ObjC), but there are two problems:

(a) interfaces cannot contain static methods

I am afraid there would be no solution at all in Java-based world, or does Groovy bring some?

(b) they force me to maintain two parallel hierarchies, like

===
interface Foo {
  def foo();
  ...
}
class Foo_Implementation implements Foo {
  def foo() { ... }
  def myfoo() { ... }
  ...
}
interface Bar implements Foo {
  def bar();
  ...
}
class Bar_Implementation extends Foo_Implementation implements Bar {
  def bar() { ... }
  ...
}
===

with a high danger of a mistake leading to inconsistence of these two hierarchies. Not speaking of the factory pattern to replace those pesky static methods, which would, alas, add a third hierarchy for factories; if I wanted to use interface/implementations for factories too, I get _four_ parallel hierarchies, which need to keep consistent! Quadruple ick.

Is there some trick in Groovy which makes this task groovier (or at the very least reasonably manageable), or am I up to my own source preprocessor and/or ASTTs (which again would clash with traits :/ )?

Thanks a lot,
OC

----------------------------------------------------------------------
This email message and any attachments are for the sole use of the intended recipient(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message and any attachments.

interface/implementation patten (was: Proxying how to?!?)

Posted by OC <oc...@ocs.cz>.
Oh, by the way,

On 30. 3. 2016, at 17:12, Jochen Theodorou <bl...@gmx.org> wrote:
> This again forces people to split their classes in interfaces and implementations

reminded me another question of mine. I actually want to embrace this pattern for a long time (after all, I am used to it from ObjC), but there are two problems:

(a) interfaces cannot contain static methods

I am afraid there would be no solution at all in Java-based world, or does Groovy bring some?

(b) they force me to maintain two parallel hierarchies, like

===
interface Foo {
  def foo();
  ...
}
class Foo_Implementation implements Foo {
  def foo() { ... }
  def myfoo() { ... }
  ...
}
interface Bar implements Foo {
  def bar();
  ...
}
class Bar_Implementation extends Foo_Implementation implements Bar {
  def bar() { ... }
  ...
}
===

with a high danger of a mistake leading to inconsistence of these two hierarchies. Not speaking of the factory pattern to replace those pesky static methods, which would, alas, add a third hierarchy for factories; if I wanted to use interface/implementations for factories too, I get _four_ parallel hierarchies, which need to keep consistent! Quadruple ick.

Is there some trick in Groovy which makes this task groovier (or at the very least reasonably manageable), or am I up to my own source preprocessor and/or ASTTs (which again would clash with traits :/ )?

Thanks a lot,
OC


Re: Proxying how to?!?

Posted by Jochen Theodorou <bl...@gmx.org>.

On 29.03.2016 18:15, OC wrote:
[...]
> class AnyClassOfMine {
>    def name
> }
>
> class DumbProxy {
>    def server
>    def propertyMissing(String name) {
>      server."$name"
>    }
> }
>
> def objects=[new AnyClassOfMine(name:"Direct"),new DumbProxy(server:new AnyClassOfMine(name:"Proxied"))]
> for (AnyClassOfMine o in objects) println "got $o.name"
> ===
>
> Alas, instead of working as expected, this fails with the aforementioned nonsensical exception:
>
> ===
> got Direct
> Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'DumbProxy@73f43791' with class 'DumbProxy' to class 'AnyClassOfMine'
> ...
> ===


There are multiple ways to "solve" the problem, but I am afraid, they 
will all look like workarounds to you... The traditional Java way would be:

interface InterfaceForAnyClassOfMine {
   def getName()
}
class AnyClassOfMine implements InterfaceForAnyClassOfMine {
   def name
}
class DumbProxy implements InterfaceForAnyClassOfMine {
    InterfaceForAnyClassOfMine server
    def getName() {
      server.name
    }
}

Then of course you would not use AnyClassOfMine as base, but 
InterfaceForAnyClassOfMine. You can make this a little bit more easy 
with @Delegate:

class DumbProxy {
   @Delegate InterfaceForAnyClassOfMine server
}

@Delegate will add the implements clause for you, as well as any compile 
time defined method of InterfaceForAnyClassOfMine... basically you safe 
a few lines. But basically DumbProxy does not have anything to do with 
AnyClassOfMine, so no runtime solution will really work here, if you 
still want to base on static types at some place.

Using runtime traits I would come up with this version:

class AnyClassOfMine { def name }
trait DumbProxy {}
def objects=[new AnyClassOfMine(name:"Proxied") as DumbProxy]
for (DumbProxy o in objects) println "got $o.name"

I think the basic problem is that you have no multiple inheritance in 
Java and only an inconsitent fraction of it in Groovy. So on the JVM I 
cannot make a class that implements a class AnyClassOfMine and DumbProxy 
at the same time. I can do such things with interfaces though. This 
again forces people to split their classes in interfaces and 
implementations, both being first class citizens. Objective C is much 
more flexible here. But it means I cannot apply the same concept to the 
JVM world... not if I want to stay with the Java class model. Our traits 
are kind of a hybrid, as they define multiple classes, one interface and 
a specific implementation. Only because of that I can make a proxy here 
and only of an interface. Dynamically generating a subclass is also 
possible, and we actually do that as well in Groovy. But once you have 
two super classes you are lost... especially without the magic 
-forwardingTargetForSelector:(SEL)sel { return self.server; }

bye Jochen

Re: Proxying how to?!? (was: changing dynamically the name of classes in a source code)

Posted by OC <oc...@ocs.cz>.
Jason,

thanks for a quick response!

On 29. 3. 2016, at 19:09, "Winnebeck, Jason" <Ja...@windstream.com> wrote:

> You still have to follow the rules of Java bytecode

right, that's why I wrote it's a Java fault (inherited by Groovy), not a Groovy fault.

> that is your class DumbProxy is not related by class hierarchy or interface to AnyClassOfMine, so you can't cast to it.

That is precisely the problem: without casting to it, it can't be used.

> You have to use def/Object type and Groovy's duck typing, or you need to make DumbProxy extend AnyClassOfMine

Far as I understand the Groovy dispatch, this would force me not to go through a relatively clean missingXXX APIs; instead, I would probably have to exploit metaclass functionality directly, or something like that.

Well OK, that I can live with (unless it gets really slow, which it probably would not).

But what if the target class is final? Would never happen with AnyClassOfMine of course, but would happen with 3rd party classes whose instances I might need to proxy.

> or make an interface for them both to implement and use that.

Same problem there: whilst I can turn AnyClassOfMine to implement anything, I can't turn 3rd party classes to do that; and proxying 3rd party classes is essential (after all, with my own classes I can easily use other tricks than proxying to achieve the same result).

> Other options to consider include:
> http://docs.groovy-lang.org/latest/html/gapi/groovy/util/Proxy.html

Correct me please if I am overlooking anything, but it seems to me this is just slightly better implementation of DumbProxy. To redirect methods it uses invokeMethod instead of methodMissing (perhaps it is faster? Dunno. One advantage might be it would technically allow to forward even methods implemented in Proxy itself, but that is prevented by the implementation); but it _does_ share the very same typecasting problem we have just established with my DumbProxy.

Or does it not? If not, how comes?

> http://docs.groovy-lang.org/latest/html/gapi/groovy/util/ProxyGenerator.html

Well this seems really to create an instance of a dynamically made subclass (whoa! But I can see there's nothing else we can do with the bloody Java inherited behaviour), but I must be missing something. That instance does not work as a proxy, but seems to be half-proxy half-real instance of the target class.

Far as I has been able to test, it seems that

pg.instantiateDelegateWithBaseClass([:],[],delegate,class)

(a) creates a new instance of (a private subclas of) given “class” (OK)
(b) which instance gets all the methods (including property getters and setters) “class” contains, directly, without notifying the “delegate” anyhow (COMPLETELY WRONG)
(c) and only properties a methods the “class” does _not_ contain are directed to the delegate (OK)

The functionality needed for proxying differs from that:

(a) the proxied object (a server) exists before a proxy is created;
(b) the delegate (far as I understand what is its purpose?!?) should get _all_ the methods called “of the proxy”...
(c) ... so that it can (pre- or post-process them if need be and) forward them to the real proxied object.

Here's my testing code; perhaps you can point out what's wrong? The documentation is seriously lacking :)

===
class AnyClassOfMine {
  def xxname // renamed from 'name' to be triple sure not to clash with proxy name or something
  def foo(bar) { println "foo of $this called with $bar"; "${bar.toUpperCase()}, I am $xxname" }
}
class Delegate {
  def server
  def propertyMissing(String name) {
    println "- delegate asked for a property '$name' for server $server"
    if (name!='xxname') return 'nonexistent'
    server."$name"
  }
  def propertyMissing(String name,value) {
    println "- delegate asked to set a property '$name' to $value for server $server"
    if (name!='xxname') return 'nonexistent'
    server."$name"
  }
  def methodMissing(String name, args) {
    println "- delegate asked for a method '$name'$args for server $server"
    if (name!='foo') return 'nonexistent'
    server."$name"(*args)
  }
}

def proxied=new AnyClassOfMine(xxname:"Proxied"),delegate=new Delegate(server:proxied)
assert delegate.xxname=='Proxied'

def pg=groovy.util.ProxyGenerator.INSTANCE // is this the proper way to do it?
def proxy=pg.instantiateDelegateWithBaseClass([:],[],delegate,delegate.server.class)
assert proxy instanceof AnyClassOfMine

println "=== Delegate gets unknown method allright:"
println "-> ${proxy.unknown('hello')}"
println "=== Known method implemented by $proxy, instead of being sent through delegate to $proxied!"
println "-> ${proxy.foo('hello')}"
println "=== It should look like this:"
println "-> ${delegate.foo('hello')}"

println "=== Exactly same problem with properties: unknown one correctly forwarded..."
println "-> $proxy.unknownProperty"
println "=== Known property though processed directly by proxy, not forwarded through delegate to $proxied!"
println "-> $proxy.xxname (differs from $proxied.xxname; or read through delegate, $delegate.xxname)"
===

The results are

===
- delegate asked for a property 'xxname' for server AnyClassOfMine@263d0564
=== Delegate gets unknown method allright:
- delegate asked for a method 'unknown'[hello] for server AnyClassOfMine@263d0564
-> nonexistent
=== Known method implemented by Delegate1_groovyProxy@837a151, instead of being sent through delegate to AnyClassOfMine@263d0564!
foo of Delegate1_groovyProxy@837a151 called with hello
-> HELLO, I am null
=== It should look like this:
- delegate asked for a method 'foo'[hello] for server AnyClassOfMine@263d0564
foo of AnyClassOfMine@263d0564 called with hello
-> HELLO, I am Proxied
=== Exactly same problem with properties: unknown one correctly forwarded...
- delegate asked for a property 'unknownProperty' for server AnyClassOfMine@263d0564
-> nonexistent
=== Known property though processed directly by proxy, not forwarded through delegate to AnyClassOfMine@263d0564!
- delegate asked for a property 'xxname' for server AnyClassOfMine@263d0564
-> null (differs from Proxied; or read through delegate, Proxied)
===

Instead, proxy.foo should redirect to the delegate (and through it to server). Similarly, proxy.xxname should get/set the server xxname (through the delegate, again).

> http://docs.groovy-lang.org/latest/html/gapi/groovy/lang/Delegate.html

Again, correct me please if I am overlooking something, but this does not seem to have _anything_ in common with the thing we are solving, i.e., proxying.

Far as I understand, this exploits ASTTs to generate automatically things like

===
class Foo {
  Bar server
  def someBarMethod() { server.someBarMethod() }
  void anotherBarMethod(foo,bar,baz) { server.anotherBarMethod(foo,bar,baz) }
  ....
  // and so forth
}
===

That's rather ugly solution compared with dynamic redirection (though it might be much faster in the Java world, I did not benchmark it, but I can guess this probably will be the point of it; along with the problem that dynamically redirected methods would not work if called from pure Java, which might be enormously important for someone, luckily, completely irrelevant to me :)).

Thanks a lot,
OC


> -----Original Message-----
> From: OC [mailto:ocs@ocs.cz] 
> Sent: Tuesday, March 29, 2016 12:16 PM
> To: users@groovy.apache.org
> Subject: Proxying how to?!? (was: changing dynamically the name of classes in a source code)
> 
> Incidentally...
> 
> On 28. 3. 2016, at 18:10, OC <oc...@ocs.cz> wrote:
>> completely absurd and very anti-object-oriented) "Cannot cast object" exception.
> 
> ... this reminded me of a problem I so far haven't been able to find a proper solution for: how the heck do you proxy in Groovy?
> 
> In ObjC, I can write
> 
> ===
> @interface AnyClassOfMine:Beanlike
> @property NSString *name;
> @end
> @implementation AnyClassOfMine @end
> 
> @interface DumbProxy:Beanlike
> @property id server;
> @end
> @implementation DumbProxy
> -forwardingTargetForSelector:(SEL)sel { return self.server; }
> @end
> 
> id objects=@[[AnyClassOfMine new:@"name":@"Direct"],[DumbProxy new:@"server":[AnyClassOfMine new:@"name":@"Proxied"]]];
> for (AnyClassOfMine *o in objects) NSLog(@"got %@",o.name);
> ===
> 
> and it works precisely as assumed, writing out
> 
> ===
> 2016-03-29 17:57:37.501 a.out[5387:707] got Direct
> 2016-03-29 17:57:37.503 a.out[5387:707] got Proxied
> ===
> 
> (Note if interested: the Beanlike superclass is irrelevant, it just simulates the new Foo(bar:bax) functionality of Groovy, which ObjC does not have, by implementing the new:(property-name):(value) method.)
> 
> Groovy -- unlike pure Java -- is smart enough to allow me to _implement_ such a proxy, but for sweet world, I cannot find a way to _use_ it?
> 
> ===
> class AnyClassOfMine {
>  def name
> }
> 
> class DumbProxy {
>  def server
>  def propertyMissing(String name) {
>    server."$name"
>  }
> }
> 
> def objects=[new AnyClassOfMine(name:"Direct"),new DumbProxy(server:new AnyClassOfMine(name:"Proxied"))]
> for (AnyClassOfMine o in objects) println "got $o.name"
> ===
> 
> Alas, instead of working as expected, this fails with the aforementioned nonsensical exception:
> 
> ===
> got Direct
> Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'DumbProxy@73f43791' with class 'DumbProxy' to class 'AnyClassOfMine'
> ...
> ===
> 
> How do you write and use a proxy in Groovy, so that it works properly?
> 
> (Note: "for (o in objects) ..." would work is this case, but would bring other problems, e.g., if there was a method "foo(AnyClassOfMine obj)" called as "for (o in objects) foo(o)", it would cause "No signature of method is applicable for argument types: (DumbProxy)".)
> 
> Thanks a lot,
> OC
> 
> ----------------------------------------------------------------------
> This email message and any attachments are for the sole use of the intended recipient(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message and any attachments.


RE: Proxying how to?!? (was: changing dynamically the name of classes in a source code)

Posted by "Winnebeck, Jason" <Ja...@windstream.com>.
You still have to follow the rules of Java bytecode, that is your class DumbProxy is not related by class hierarchy or interface to AnyClassOfMine, so you can't cast to it. You have to use def/Object type and Groovy's duck typing, or you need to make DumbProxy extend AnyClassOfMine or make an interface for them both to implement and use that.

Other options to consider include:
http://docs.groovy-lang.org/latest/html/gapi/groovy/util/Proxy.html
http://docs.groovy-lang.org/latest/html/gapi/groovy/util/ProxyGenerator.html
http://docs.groovy-lang.org/latest/html/gapi/groovy/lang/Delegate.html

Jason

-----Original Message-----
From: OC [mailto:ocs@ocs.cz] 
Sent: Tuesday, March 29, 2016 12:16 PM
To: users@groovy.apache.org
Subject: Proxying how to?!? (was: changing dynamically the name of classes in a source code)

Incidentally...

On 28. 3. 2016, at 18:10, OC <oc...@ocs.cz> wrote:
> completely absurd and very anti-object-oriented) "Cannot cast object" exception.

... this reminded me of a problem I so far haven't been able to find a proper solution for: how the heck do you proxy in Groovy?

In ObjC, I can write

===
@interface AnyClassOfMine:Beanlike
@property NSString *name;
@end
@implementation AnyClassOfMine @end

@interface DumbProxy:Beanlike
@property id server;
@end
@implementation DumbProxy
-forwardingTargetForSelector:(SEL)sel { return self.server; }
@end

id objects=@[[AnyClassOfMine new:@"name":@"Direct"],[DumbProxy new:@"server":[AnyClassOfMine new:@"name":@"Proxied"]]];
for (AnyClassOfMine *o in objects) NSLog(@"got %@",o.name);
===

and it works precisely as assumed, writing out

===
2016-03-29 17:57:37.501 a.out[5387:707] got Direct
2016-03-29 17:57:37.503 a.out[5387:707] got Proxied
===

(Note if interested: the Beanlike superclass is irrelevant, it just simulates the new Foo(bar:bax) functionality of Groovy, which ObjC does not have, by implementing the new:(property-name):(value) method.)

Groovy -- unlike pure Java -- is smart enough to allow me to _implement_ such a proxy, but for sweet world, I cannot find a way to _use_ it?

===
class AnyClassOfMine {
  def name
}

class DumbProxy {
  def server
  def propertyMissing(String name) {
    server."$name"
  }
}

def objects=[new AnyClassOfMine(name:"Direct"),new DumbProxy(server:new AnyClassOfMine(name:"Proxied"))]
for (AnyClassOfMine o in objects) println "got $o.name"
===

Alas, instead of working as expected, this fails with the aforementioned nonsensical exception:

===
got Direct
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'DumbProxy@73f43791' with class 'DumbProxy' to class 'AnyClassOfMine'
...
===

How do you write and use a proxy in Groovy, so that it works properly?

(Note: "for (o in objects) ..." would work is this case, but would bring other problems, e.g., if there was a method "foo(AnyClassOfMine obj)" called as "for (o in objects) foo(o)", it would cause "No signature of method is applicable for argument types: (DumbProxy)".)

Thanks a lot,
OC

----------------------------------------------------------------------
This email message and any attachments are for the sole use of the intended recipient(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message and any attachments.

Proxying how to?!? (was: changing dynamically the name of classes in a source code)

Posted by OC <oc...@ocs.cz>.
Incidentally...

On 28. 3. 2016, at 18:10, OC <oc...@ocs.cz> wrote:
> completely absurd and very anti-object-oriented) “Cannot cast object” exception.

... this reminded me of a problem I so far haven't been able to find a proper solution for: how the heck do you proxy in Groovy?

In ObjC, I can write

===
@interface AnyClassOfMine:Beanlike
@property NSString *name;
@end
@implementation AnyClassOfMine @end

@interface DumbProxy:Beanlike
@property id server;
@end
@implementation DumbProxy
-forwardingTargetForSelector:(SEL)sel { return self.server; }
@end

id objects=@[[AnyClassOfMine new:@"name":@"Direct"],[DumbProxy new:@"server":[AnyClassOfMine new:@"name":@"Proxied"]]];
for (AnyClassOfMine *o in objects) NSLog(@"got %@",o.name);
===

and it works precisely as assumed, writing out

===
2016-03-29 17:57:37.501 a.out[5387:707] got Direct
2016-03-29 17:57:37.503 a.out[5387:707] got Proxied
===

(Note if interested: the Beanlike superclass is irrelevant, it just simulates the new Foo(bar:bax) functionality of Groovy, which ObjC does not have, by implementing the new:(property-name):(value) method.)

Groovy -- unlike pure Java -- is smart enough to allow me to _implement_ such a proxy, but for sweet world, I cannot find a way to _use_ it?

===
class AnyClassOfMine {
  def name
}

class DumbProxy {
  def server
  def propertyMissing(String name) {
    server."$name"
  }
}

def objects=[new AnyClassOfMine(name:"Direct"),new DumbProxy(server:new AnyClassOfMine(name:"Proxied"))]
for (AnyClassOfMine o in objects) println "got $o.name"
===

Alas, instead of working as expected, this fails with the aforementioned nonsensical exception:

===
got Direct
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'DumbProxy@73f43791' with class 'DumbProxy' to class 'AnyClassOfMine'
...
===

How do you write and use a proxy in Groovy, so that it works properly?

(Note: “for (o in objects) ...” would work is this case, but would bring other problems, e.g., if there was a method “foo(AnyClassOfMine obj)“ called as “for (o in objects) foo(o)”, it would cause “No signature of method is applicable for argument types: (DumbProxy)”.)

Thanks a lot,
OC


Re: changing dynamically the name of classes in a source code

Posted by OC <oc...@ocs.cz>.
Weird... that's probably a question for Jochen on another guru. Perhaps Lists work in a special way, different from other classes? No idea; I just have tested and found it works.

Indeed, with my own class instead of List it leads to the (completely absurd and very anti-object-oriented) “Cannot cast object” exception.

That's precisely the terrible mess which causes Java to be one of the worst languages for learning :(

All the best,
OC


On 28. 3. 2016, at 15:53, frenchy48 <ba...@in2p3.fr> wrote:

> Thanks for replying
> as a side note OOP appear only in chapter 8 of my book so I have to survive
> in the meantime 
> A long long time ago I used object logo ... sticking to groovy helps me to
> provide the additional codes I want to create simplistic graphics.
> 
> now back to the main point:
> when I read your example I thought "good Lord I wasn't even aware of that!
> how come?"
> then I tested .... and 
> 
> ---------------
> org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast
> object
> 'scrountch.geom.SFrame[frame1,0,23,300x442,layout=java.awt.BorderLayout,title=,maximized]'
> with class 'scrountch.geom.SFrame' to class 'Cadre'
> --------------
> with 
> 
> (SFrame being a groovy class of the framework)
> 
> but 
> 
> does work ....
> 
> so ???? what's the difference?
> 
> 
> OC wrote
>>> now if you have a factory that returns the proper class and you assign it
>>> to
>>> a variable typed with a subclass it won't work.
>> 
>> ===
>> 26 /tmp> &lt;w.groovy
>> class Localizeděščřžýáíí extends LinkedList { }
>> class Factory { static LinkedList list() { return new LinkedList() } }
>> 
>> Localizeděščřžýáíí ěěě=Factory.list()
>> ěěě&lt;&lt;&quot;Actually, it does work, though in Java-based language
>> it's a small miracle&quot;
>> println &quot;${ěěě.class.simpleName} contains $ěěě&quot;
>> 27 /tmp&gt; groovy w 
>> Localizeděščřžýáíí contains [Actually, it does work, though in Java-based
>> language it's a small miracle]
>> 28 /tmp> 
>> ===
> 
> 
> 
> 
> 
> -----
> member of Grumpy Old Programmers
> --
> View this message in context: http://groovy.329449.n5.nabble.com/changing-dynamically-the-name-of-classes-in-a-source-code-tp5732080p5732085.html
> Sent from the Groovy Users mailing list archive at Nabble.com.


Re: changing dynamically the name of classes in a source code

Posted by frenchy48 <ba...@in2p3.fr>.
Thanks for replying
as a side note OOP appear only in chapter 8 of my book so I have to survive
in the meantime 
A long long time ago I used object logo ... sticking to groovy helps me to
provide the additional codes I want to create simplistic graphics.

now back to the main point:
when I read your example I thought "good Lord I wasn't even aware of that!
how come?"
then I tested .... and 

---------------
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast
object
'scrountch.geom.SFrame[frame1,0,23,300x442,layout=java.awt.BorderLayout,title=,maximized]'
with class 'scrountch.geom.SFrame' to class 'Cadre'
--------------
with 

(SFrame being a groovy class of the framework)

but 

does work ....

so ???? what's the difference?


OC wrote
>> now if you have a factory that returns the proper class and you assign it
>> to
>> a variable typed with a subclass it won't work.
> 
> ===
> 26 /tmp> &lt;w.groovy
> class Localizeděščřžýáíí extends LinkedList { }
> class Factory { static LinkedList list() { return new LinkedList() } }
> 
> Localizeděščřžýáíí ěěě=Factory.list()
> ěěě&lt;&lt;&quot;Actually, it does work, though in Java-based language
> it's a small miracle&quot;
> println &quot;${ěěě.class.simpleName} contains $ěěě&quot;
> 27 /tmp&gt; groovy w 
> Localizeděščřžýáíí contains [Actually, it does work, though in Java-based
> language it's a small miracle]
> 28 /tmp> 
> ===





-----
member of Grumpy Old Programmers
--
View this message in context: http://groovy.329449.n5.nabble.com/changing-dynamically-the-name-of-classes-in-a-source-code-tp5732080p5732085.html
Sent from the Groovy Users mailing list archive at Nabble.com.

Re: changing dynamically the name of classes in a source code

Posted by OC <oc...@ocs.cz>.
> one of my main message in my course is to have  variables with a type!
> so "def x" is not encouraged (not even taught)!

Well, that's arguable at best.

Whilst declaring variables is highly _practical_ for it helps to prevent typos and allows both the IDE and compiler to assist the programmer, _conceptually_ it is very wrong. The concept of object programming is that an object is an object is an object; all objects are conceptually equal, and each object can be sent any message (well, the Java howler of “calling methods” instead of the proper paradigm of “sending messages” does not help either :( ).

All in all, given you don't teach Groovy but programming, I would strongly recommend to use some variant of Smalltalk instead -- it is less practical for everyday purposes, but allows the students to grok the principles of OOP _much_ better than anything Java-based ever might.

> now if you have a factory that returns the proper class and you assign it to
> a variable typed with a subclass it won't work.

===
26 /tmp> <w.groovy
class Localizeděščřžýáíí extends LinkedList { }
class Factory { static LinkedList list() { return new LinkedList() } }

Localizeděščřžýáíí ěěě=Factory.list()
ěěě<<"Actually, it does work, though in Java-based language it's a small miracle"
println "${ěěě.class.simpleName} contains $ěěě"
27 /tmp> groovy w 
Localizeděščřžýáíí contains [Actually, it does work, though in Java-based language it's a small miracle]
28 /tmp> 
===

?

All the best,
OC


Re: changing dynamically the name of classes in a source code

Posted by frenchy48 <ba...@in2p3.fr>.
Ok  students will learn more english later ... but please!
(for instance have a look at Scratch or read this:
https://rising.globalvoices.org/blog/2013/03/18/programming-possibilities-writing-code-in-arabic/)


Now subclassing does not work:
my course is using a subset of groovy (my goal is to teach programming not
full Groovy)
one of my main message in my course is to have  variables with a type!
so "def x" is not encouraged (not even taught)!
now if you have a factory that returns the proper class and you assign it to
a variable typed with a subclass it won't work.
 






-----
member of Grumpy Old Programmers
--
View this message in context: http://groovy.329449.n5.nabble.com/changing-dynamically-the-name-of-classes-in-a-source-code-tp5732080p5732082.html
Sent from the Groovy Users mailing list archive at Nabble.com.

Re: changing dynamically the name of classes in a source code

Posted by OC <oc...@ocs.cz>.
Well, I can't resist commenting that a programmer would need English anyway :)

That said, can't you simply sublass? Like

===
class Localizeděščřžýáíí extends LinkedList { }

def ěěě=new Localizeděščřžýáíí()
ěěě<<'Hello'
ěěě<<'note that both class and variable names'
ěěě<<'support accented characters all right'
println "${ěěě.class.simpleName} contains $ěěě"
===

As for variables and argument names, you don't need anything at all for the latter, nothing but 'def' for the former.

All the best,
OC


On 27. 3. 2016, at 17:38, frenchy48 <ba...@in2p3.fr> wrote:

> Before asking a question I'l have first to explain WHY this question.  
> 
> I have been writing a book about programming (for beginners)  
> 
> For the labs I use  a small subset of Groovy  
> now my labs are slightly boring so I decided to write a small graphical
> library to facilitate the design of funnier experiments.  
> 
> This small library is built around about 20 groovy classes and provides a
> simple framework to do some graphical programming.  
> 
> The people going to use this codes are not english speaking people.  
> But it's not a big problem when limiting the use of english to some keywords
> (for, while, if,...) or a limited number of types such as List or Map.  
> 
> But if I introduce more classes it may be a problem.  
> 
> So I started thinking about internationalisation of code.  
> 
> For my limited number of classes I implemented a "methodMissing" feature
> that implements a translation of method names.  
> it works (though error handling is not perfect and can be confusing)  
> 
> Now I was wondering if I could translate the name of this library's classes
> at runtime.
> (there are already languages such as Scratch which are translated in the
> user's language -including keywords ... but I don't need to go that far-)  
> 
> And here are my questions : how to do that and is it worth the trouble?  
> 
> I toyed with the idea of using ASTTransformation but I really don't know how
> to visit my class names and if I can change them at runtime.  
> Since the programming features are limited the students are not going to use
> the constructors of the classes (there are only factories).
> So the only places where the class names should be changed is when declaring
> variables or parameter types.  
> (I could sed the source code but I would rather not)  
> 
> so is this transformation doable? when? (parsing or semantic?) how?
> (performance is not an issue and  students program through the
> groovyconsole)  
> 
> (for sure error handling is going to be even more problematic when the user
> sees a message pertaining to a class which is "under the hood")  
> 
> Any advice?  
> 
> thanks  
> 
> 
> 
> 
> -----
> member of Grumpy Old Programmers
> --
> View this message in context: http://groovy.329449.n5.nabble.com/changing-dynamically-the-name-of-classes-in-a-source-code-tp5732080.html
> Sent from the Groovy Users mailing list archive at Nabble.com.


Re: changing dynamically the name of classes in a source code

Posted by Jochen Theodorou <bl...@gmx.org>.

On 28.02.2017 16:59, frenchy48 wrote:
> well a last response to the initial message.

there was an initial message? I seem not to have gotten one.

bye Jochen

Re: changing dynamically the name of classes in a source code

Posted by frenchy48 <ba...@in2p3.fr>.
well a last response to the initial message.
Though many may think it's useless to change the name of classes and methods
I succeeded in implementing a framework (for teaching) that just does that
... next step: may be change also the language keywords dynamically (please
don't shoot: don't shoot a sitting bird! ;-) but if a newbie with an arabic
keyboard can learn to program I will consider myself happy)
the Web site (mostly in French! Sorry) : http://scrountch.info



-----
member of Grumpy Old Programmers
--
View this message in context: http://groovy.329449.n5.nabble.com/changing-dynamically-the-name-of-classes-in-a-source-code-tp5732080p5738844.html
Sent from the Groovy Users mailing list archive at Nabble.com.