Coming from a Java background, I know that for example an ID can be implemented as a generic like this:
public class Id<T> {
private String _id;
private Id(String idString) {
this._id = idString;
}
public static <Type> Id<Type> valueOf(String idString) {
return new Id<Type>(idString);
}
}
Id<ObjectA> a = Id.valueOf("1");
Id<ObjectB> b = Id.valueOf("1");
In this example, even though both IDs hold the String "1", they cannot be compared since their generic types are different.
I'm trying to implement the same structure in Python and started out with a NamedTuple:
from typing import NamedTuple
class Id(NamedTuple):
id: str
def __eq__(self, other):
if not isinstance(other, Id):
return False
else:
if self.id != other.id:
return False
return True
I want to bring generics in so that I can create an Id just like in Java. Is that possible and if so, how?
Related
I want to retrieve the annotation value used from MyAnnot. I am getting 3 annotations in the list even though there are only 2. Also, I have tried obtaining the used field of MyAnnot but with no success. I would like to return a map where MyAnnot's used is the key and type as the map's value.
// Then, define your class with it's annotated Fields
class MyClass {
#MyAnnot(used = "Hey", type = "There")
String fielda
#MyAnnot(used = "denn", type = "Ton")
String fieldc
}
def findAllPropertiesForClassWithAnotation(obj, annotClass) {
def op = []
def annos = []
def i = 0
obj.properties.findAll { prop ->
obj.getClass().declaredFields.find {
it.name == prop.key && annotClass in it.declaredAnnotations*.annotationType()
annos=it.declaredAnnotations
i++
if(annos)
op << annos[0] as Set
// println"Props ${annos[0]}"
}
}
op.each{ println "${it} and i is ${i}"}
}
// Then, define an instance of our class
MyClass a = new MyClass(fielda: 'tim', fieldc: 'dennisStar')
// And print the results of calling our method
println findAllPropertiesForClassWithAnotation(a, MyAnnot)
First of all you need to mark you annotation with: #Retention(RetentionPolicy.RUNTIME) to make it available for processing at runtime, so it will be:
#Retention(RetentionPolicy.RUNTIME)
#interface MyAnnot {
String used()
String type()
}
Then, used and type are not fields, nor properties but methods, so they must be invoked and get.
The script will be:
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Retention
#Retention(RetentionPolicy.RUNTIME)
#interface MyAnnot {
String used()
String type()
}
class MyClass {
#MyAnnot(used="Hey" ,type="There")
String fielda
#MyAnnot(used="denn", type="Ton")
String fieldc
}
def findAllPropertiesForClassWithAnotation( obj, annotClass ) {
def c = obj.getClass()
c.declaredFields.findAll { field ->
field.isAnnotationPresent(annotClass)
}.collect { found ->
def a = found.getAnnotation(annotClass)
[(a.used()): a.type()]
}.sum()
}
MyClass a = new MyClass(fielda: 'tim', fieldc: 'dennisStar')
println findAllPropertiesForClassWithAnotation(a, MyAnnot)
Mind that passing only a class of annotation is not sufficient, since you don't know the methods (used and type) to be invoked on the annotation. The following method will work only for MyAnnot class.
I really like the groovy language but I believe my java experience is leading me to a path where I don't use groovys fully potential.
I have a scenario where a groovy object (Master.groovy) sends some json-data to some view that creates a form out of this data. Then the user can submit this form and Master.groovy receives it as json-data again.
Master.groovy can access a pool of different form descriptions (formDesc1, formDesc2, etc.) which it choses from when sending the json to the view. When the user returns the json data - Master.groovy will then pass it over to e.g. formDesc1 to validate it.
This is how it looks with code:
Master.groovy
class Master {
FormDesc[] formDescs = [new FormDesc1(), new FormDesc2(), new FormDesc2()]
def getJSONform(Integer formId){
return formDescs[formId].getForm()
}
def validateForm(Integer formId, def data) {
return formDescs[formId].validate(data)
}
}
FormDesc1.groovy
class FormDesc1 extends FormDesc {
static String name = "alias"
FormDesc1 (){
form.add(new InputElement(name:name, type:"text"))
form.add(new TextArea(name:"msg", rows:"12", cols:"12"))
}
#Override
def validate(data){
errors = []
if(data.get(name)["value"] != "form1")
errors.add("name not allowed")
return errors
}
}
FormDesc2.groovy
class FormDesc2 extends FormDesc {
static String name = "alias"
FormDesc1 (){
form.add(new InputElement(name:name, type:"text"))
form.add(new TextArea(name:"msg", rows:"12", cols:"12"))
}
#Override
def validate(data){
errors = []
if(data.get(name)["value"] != "form1")
errors.add("name not allowed")
return errors
}
}
There can be many forms in the package /forms and to load all of them in the memory seems very unnecessary. And it would be much nicer if the formDesc consisted of json-data that represented the form and then only has the method validate. E.g:
FormDescUltimate.groovy
class FormDescUltimate extends FormDesc {
form = loadJSONFile("formDescUltimate.json")
#Override
def validate(data){
errors = []
if(data.get("alias")["value"] != "form1")
errors.add("name not allowed")
return errors
}
}
formDescUltimate.json
{
'formId' : 'ultimate_form',
'elements': [
{'InputElement' : {'name': 'alias', 'type':'text'}},
{'TextArea' : {'name': 'msg', 'rows':'12', 'cols':'12'}}
]
}
Is it possible to achieve this nicely with groovy, or is there any better design to accomplish this?
Thanks in advance and sorry for the long post!
Given the following Groovy class:
class MyClass {
def someClosure = {}
def someClosure2 = {}
private privateClosure = {
}
def someVal = 'sfsdf'
String someMethod() {}
}
I need a way to retrieve the names of all public properties that have closure assigned to them, so the correct result for this class would be ['someClosure', 'someClosure2'].
I can assume that all the classes of interest have a default constructor, so if it makes things easier, I could retrieve the properties from an instance via
def instance = MyClass.newInstance()
You can simply check the value of every groovy property:
class Test {
def aClosure = {}
def notClosure = "blat"
private privateClosure = {}
}
t = new Test()
closurePropNames = t.properties.findResults { name, value ->
value instanceof Closure ? name : null
}
assert closurePropNames == ['aClosure']
The private fields are not considered groovy properties, so they won't be included in the results.
I have a mixin class that bundles functionality for different types that do not share a common heritage. The mixing is applied using the #Mixin annotation, so it is handled at compile time.
Some of the mixin methods return this as the result of a method call. The problem is that the this is of the mixing type and not the type of the base class. When I want to work typed in the rest of the application a ClassCastException is thrown saying that the mixing type can not be cast to the base type.
In the example code below return this returns an object of type AMixin instead of an Object of type BaseClass.
How can I have return this return an object of type BaseClass instead of an object of type AMixin?
class AMixin {
def getWhatIWant(){
if(isWhatIwant){
return this
} else {
getChildWhatIWant()
}
}
def getChildWhatIWant(){
for (def child in childred) {
def whatIWant = child.getWhatIWant()
if (whatIWant) {
return whatIWant
}
}
return null
}
}
#Mixin(AMixin)
class BaseClass {
boolean isWhatiWant
List<baseClass> children
}
I just ran into this same situation. I solved it by setting 'this' from the concrete class into a private variable 'me' inside the concrete class and return 'me' in the Mixin classes. For example:
class MyMixin {
def mixinMethod() {
// do stuff
return me
}
}
#Mixin(MyMixin)
class MyConcreteClass {
private MyConcreteClass me
MyConcreteClass() {
me = this
}
}
I feel like it's a bit kludgy, but I think it's a lot simpler than this other solution. I personally need the ability to use the same Mixin in multiple classes, and it sounds like this other proposed solution would not allow for that if you cannot assign multiple Categories to a single Mixin class.
I created the class Base added the category to the AMixin Class and the BaseClass extends from Base.....(http://groovy.codehaus.org/Category+and+Mixin+transformations)
Executed this in GroovyConsole I get
BaseClass#39c931fb
class Base {
boolean isWhatIwant
List<BaseClass> children
}
#Category(Base)
class AMixin {
def getWhatIWant(){
if(isWhatIwant){
return this
} else {
getChildWhatIWant()
}
}
def getChildWhatIWant(){
for (def child in children) {
def whatIWant = child.getWhatIWant()
if (whatIWant) {
return whatIWant
}
}
return null
}
}
#Mixin(AMixin)
public class BaseClass extends Base {
}
def b = new BaseClass(isWhatIwant:true)
println b.getWhatIWant()
EDIT just a DummyClass. I know it's very awkward that It works....I'm sure Guillaume Laforge could answer how this works...
class DummyClass {
}
#Category(DummyClass)
class AMixin {
def getWhatIWant(){
if(isWhatIwant){
return this
} else {
getChildWhatIWant()
}
}
def getChildWhatIWant(){
for (def child in children) {
def whatIWant = child.getWhatIWant()
if (whatIWant) {
return whatIWant
}
}
return null
}
}
#Mixin(AMixin)
public class BaseClass extends DummyClass {
boolean isWhatIwant
List<BaseClass> children
}
def b = new BaseClass(isWhatIwant:true)
println b.getWhatIWant()
I have this code in Groovy:
class Person {
def age
Person () {
println age // null
}
}
def p = new Person ([age: '29'])
println p.age // 29
I need to read age value in constructor, but it isn't setted yet.
How can I do this?
Note: I don't want to use a init() method and call manually every time, like
class Person {
def age
def init() {
println age // now have 29
}
}
def p = new Person ([age: '29'])
p.init()
println p.age // 29
Link to GroovyConsole.
Thanks!
You can write a constructor like this:
class Person {
def age
Person(Map map) {
for (entry in map) {
this."${entry.key}" = entry.value
}
println age
}
}
If you're using groovy 1.8, take a look at the #TupleConstructor annotation, which will automatically build a constructor like the one above, as well as a list based one.
import groovy.transform.TupleConstructor
#TupleConstructor
class Person {
int age
}
p = new Person([age: 99])
assert p.age == 99