I have two classes. One.groovy:
class One {
One() {}
def someMethod(String hey) {
println(hey)
}
}
And Two.groovy:
class Two {
def one
Two() {
Class groovy = ((GroovyClassLoader) this.class.classLoader).parseClass("One.groovy")
one = groovy.newInstance()
one.someMethod("Yo!")
}
}
I instantiate Two with something like this:
GroovyClassLoader gcl = new GroovyClassLoader();
Class cl = gcl.parseClass(new File("Two.groovy"));
Object instance = cl.newInstance();
But now I get groovy.lang.MissingMethodException: No signature of method: script13561062248721121730020.someMethod() is applicable for argument types: (java.lang.String) values: [Yo!]
Any ideas?
Seems like it is occurring due to the groovy class loader method being called: the string one is to parse a script in text format. Using the File one worked here:
class Two {
def one
Two() {
Class groovy = ((GroovyClassLoader) this.class.classLoader).parseClass("One.groovy")
assert groovy.superclass == Script // whoops, not what we wanted
Class groovy2 = ((GroovyClassLoader) this.class.classLoader).parseClass(new File("One.groovy"))
one = groovy2.newInstance()
assert one.class == One // now we are talking :-)
one.someMethod("Yo!") // prints fine
}
}
Related
I'm defining some custom Exceptions in Dart.
I want in my logic to check the type of exception and base my processing on that, so I want to create distinct classes for each, for example like this :
class FailedToLoadCriticalDataException implements Exception { } // app cannot continue
class FailedToLoadNonCriticalDataException implements Exception { } // app can continue
However I also want to pass 2 parameters when I create these types of exceptions, the type of API call, and the API url, and the definition for that would look like this :
class UrlCallFailedException implements Exception {
String _dataTypeName;
String _urlEndpoint;
UrlCallFailedException([this._dataTypeName, this._urlEndpoint]);
#override
String toString() {
return "(${this.runtimeType.toString()}) Failed to fetch $_dataTypeName ($_urlEndpoint)";
}
}
Now what I want to do is (replace the initial definitions I made earlier and re)define my FailedToLoadCriticalDataException and FailedToLoadNonCriticalDataException classes so that they are exactly the code that is in the UrlCallFailedException class.
Is there any way to simply say something like class FailedToLoadCriticalDataException **is** UrlCallFailedException; and not need to duplicate the code that defines UrlCallFailedException ?
class FailedToLoadCriticalDataException implements UrlCallFailedException{ } is wrong because it is "Missing concrete implementations of 'getter UrlCallFailedException._dataTypeName',.."
class FailedToLoadCriticalDataException extends UrlCallFailedException{ } is wrong because when I got to throw FailedToLoadNonCriticalDataException("Foo", url); it's expectation is that there are no params ("Too many positional arguments: 0 expected, but 2 found.").
Is there a way to create multiple classes that behave exactly the same as another type and differ only in their class, without duplicating all the code ?
I've come up with this as a decent compromise :
class FailedToLoadCriticalDataException extends UrlCallFailedException {
FailedToLoadCriticalDataException([dataTypeName, urlEndpoint]) {
super._dataTypeName = dataTypeName;
super._urlEndpoint = urlEndpoint;
}
}
class FailedToLoadNonCriticalDataException extends UrlCallFailedException {
FailedToLoadNonCriticalDataException([dataTypeName, urlEndpoint]) {
super._dataTypeName = dataTypeName;
super._urlEndpoint = urlEndpoint;
}
}
Some, but minimal, code duplication, and I can now call throw FailedToLoadNonCriticalDataException("Foo", url); in my code later.
In Swift we usually use extensions as a way to organize methods in separate blocks and even files. This makes code much cleaner but it also allows us to do some tricks such as:
class API {}
extension API {
class Lists{}
}
extension Lists {
class Posts {
func latest() -> [Post] {
// get latest posts from a REST api
}
}
}
We can put any of the extension blocks in a separate file and it works perfectly in Swift.
Now one do the following to get the latest posts from the API in a clean way
let posts = API.Lists.Posts.latest()
Trying to convert that code into Kotlin I used SwiftKotlin converter tool that I thought that might work but it doesn't compile as It seems to be invalid:
class API {}
class API.Lists {}
class Lists.Posts {
companion object {
fun latest() {
// get posts
}
}
}
So I came up with the following that works fine and also compiles but it's not suitable for my case as methods can be quite long and I can't afford to have them all in one class in one file and I don't know how I can split them in multiple files.
class API {
class Lists {
class Posts {
companion object {
fun latest() {
}
}
}
}
}
Any suggestion is appreciated.
To put an extension on a companion object, you can write
fun API.Lists.Posts.Companion.latest() ...
You still need
class API {
class Lists {
class Posts {
companion object {
}
}
}
}
in a single file, but extensions can be defined elsewhere.
If you just want to mimic usage of these calls, you can use objects, like this for example:
object ApiPosts {
fun latest() {}
}
object ApiLists {
val Posts = ApiPosts
}
object API {
val Lists = ApiLists
}
API.Lists.Posts.latest()
But this is really not a Kotlin way, and in common case it's a bad practice to write in a language the way it's not supposed to.
One possible solution is to just extend the inner classes with normal functions not static ones (companion):
class ParentClass {
class InnerClass {
}
}
And in any other file you could do:
fun ParentClass.InnerClass.instanceMember() {
}
And for usage:
ParentClass.InnerClass().instanceMember()
Of course this isn't exactly like the Swift version but it's close enough.
I'm having a very simple restful controller, which looks like this:
class PersonController extends RestfulController<Person> {
static responseFormats = ['json', 'xml']
PersonController() {
super(Person)
}
}
However, now I want to add a search option to this. What is the Grails way of making this possible?
I thought of adding the following:
def search(Map params) {
println params
}
But that makes Grails (2.3) crash (| Error Fatal error during compilation org.apache.tools.ant.BuildException: Compilation Failed (Use --stacktrace to see the full trace)).
So what is the right way of adding this? I'm looking for some solution which I can call using http://localhost:8080/foo/person/search?q=erik
This is my UrlMappings:
static mappings = {
"/$controller/$action?/$id?(.${format})?"{
constraints {
// apply constraints here
}
}
"/rest/persons"(resources:'Person')
I've changed the above to:
def search() {
println params
}
And that doesn't give the compilation error anymore, but I still get this error:
TypeMismatchException occurred when processing request: [GET] /declaratie-web/rest/medicaties/search - parameters:
q: erik
Provided id of the wrong type for class nl.Person. Expected: class java.lang.Long, got class java.lang.String. Stacktrace follows:
org.hibernate.TypeMismatchException: Provided id of the wrong type for class nl.Person. Expected: class java.lang.Long, got class java.lang.String
I also found out that it doesn't matter how I call the controller:
http://localhost:8080/foo/person/search?q=erik
http://localhost:8080/foo/person/search222?q=erik
http://localhost:8080/foo/person/search39839329?q=erik
All fails with the above error, so it seems my method is ignored (maybe caused by my URLmapping?)
You really aren't being RESTful by doing that. q should just be a parameter for the index action. You can override that method to include your functionality.
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
def c = Person.createCriteria()
def results = c.list(params) {
//Your criteria here with params.q
}
respond results, model:[personCount: results.totalCount]
}
#james-kleeh solution is right, but you can do it more clean by override the listAllResources method which is called by index
#Override
protected List<Payment> listAllResources(Map params) {
Person.createCriteria().list(params) {
// Your criteria here with params.q
}
}
I'd like to write my own macro for creating property like objects in Haxe.
This question is not so much about properties but more about writing macros.
(probably NME has already a macro for that).
having this class in haxe
class Foo {
#:property var bar:String;
}
I like this to be expanded into
class Foo {
private var bar:String;
public function setBar(_val:String):void {
this.bar = _val;
}
public function getBar():String {
return this.bar;
}
}
I read the corresponding docs but honestly I find them very confusing.
thanks
You might want to take a look at how tinkerbell resolves the same issue: https://github.com/back2dos/tinkerbell/wiki/tink_lang#wiki-accessors
This Type Builder example (pasted below for reference, but there's better description at the link) found in the Haxe Manual is a nice, simple example of adding a function to a Class.
Adding a property would be much the same. I added a trace(field) loop to help get a feel for how they're defined:
Main.hx
#:build(TypeBuildingMacro.build("myFunc"))
class Main {
static public function main() {
trace(Main.myFunc); // my default
}
}
TypeBuildingMacro.hx
import haxe.macro.Context;
import haxe.macro.Expr;
class TypeBuildingMacro {
macro static public function build(fieldName:String):Array<Field> {
var fields = Context.getBuildFields();
for (field in fields) { trace(field); }
var newField = {
name: fieldName,
doc: null,
meta: [],
access: [AStatic, APublic],
kind: FVar(macro : String, macro "my default"),
pos: Context.currentPos()
};
fields.push(newField);
return fields;
}
}
Note that Main.hx must invoke the macro with the #:build metadata, so the compiler knows to run the macro (which adds the function) before processing the Main class itself.
I have a domain class that looks like this:
class Offerbyuser {
Number offerPrice
Number minHours
static constraints = {}
}
Then in a controller, I do this:
def offer = new Offerbyuser(offerPrice:1, minHours:3)
offer is always NULL. Why? Am I missing something obvious?
UPDATE: so this DOES work, but what's not working I found out is the method after that.
user.addToOutgoingOffers(offer)
user has a one-to-many relationship with Offerbyuser domain class:
class User {
static hasMany = [outgoingOffers:Offerbyuser]
}
I get this error:
groovy.lang.MissingMethodException: No signature of method: twitter4j.UserJSONImpl.addToOutgoingOffers() is applicable for argument types: (test.Offerbyuser) values: [Offer by user - Price: 1, Tweet hours: 3]
Your code works fine for me. I think that it maybe your controller class is not in the same package with your domain class, and you maynot include the domain class. Grails can not find the class you "new", but since Groovy is a dynamic language it won't throw an error.
Please try this:
In domain class
package test
class Offerbyuser {
...
}
In controller:
package test
class TestController {
...
def doSomething = {
def offer = new Offerbyuser(offerPrice:1, minHours:5)
}
}