When I have a Java method that takes a BigDecimal parameter:
public void setAmount(BigDecimal amount)
then I can call it from Groovy using an integer argument like
m.setAmount(11)
Can anybody point me to Groovy documentation where this type coercion (?) is defined?
Extract from https://docs.groovy-lang.org/docs/next/html/documentation/core-semantics.html#_method_resolution
An argument o of type A can be used for a parameter of type T if and only if:
...
or T and A derive from java.lang.Number and conform to the same rules as assignment of numbers
When I then look at the referenced rules for "assignment of numbers", there is no mention of T being BigDecimal:
https://docs.groovy-lang.org/docs/next/html/documentation/core-semantics.html#number-assignment
In this question Converting Integer to BigDecimal in Groovy the answer gives a reference to Groovy's BigDecimalCachedClasscoerceArgument(Object argument).
That method now even has a simpler implementation:
public Object coerceArgument(Object argument) {
if (argument instanceof Number) {
return NumberMath.toBigDecimal((Number) argument);
}
return argument;
}
So: Is the documentation just outdated?
Related
void main() {
final list = [1].cast<int>();
print('${list.runtimeType}'); // prints CastList<int, int>
}
When I type lis..., Android Studio code completion infers the type as List<int> which it is but when I use runtimeType on it, it prints CastList<int, int>.
Is this IDE fault or Dart?
The cast method is specified to return a List:
List<R> cast <R>()
So this is what your IDE are based on since this is the only guarantee your get. But since other classes can extend/implement List, we are also allowed to return a class which extends from List and return objects based on this new type of List.
E.g. in you example we can see that cast actually returns an instance of CastList. But since CastList implements the interface of List the cast method are allowed to return the CastList instance.
And this is one of the reason why you should never really use runtimeType for anything other than debugging. runtimeType will return the specific type of the object without any details about implemented interfaces.
Instead, you should use the is operator if you want to test for a given type like:
if (obj is List<int>)
The is operator will test if obj implements the interface of e.g. List<int> and not just test if obj is created from this specific class.
I am a little stumped at the moment. How do I write a method in a sub-class which overrides an abstract method and accepts only String and boolean values?
All derived abstract Methods must have the same signature. Meaning the name and number of parameters as the method declared in superclass. So if your abstract class have String and boolean prameters you can do that by coping the signature in your subclass and adding your own definition.
Here is an example:
public void myMethod(String myString, Boolean b)
If you want to have different signature, then it doesn't make sense to extend the abstract class.
Also checkout this tutorial about abstract classes and methods in Java
http://beginnersbook.com/2013/05/java-abstract-class-method/
This Groovy script runs fine:
println 0;
class MyClass
{
public MyClass(int j) {};
public MyClass method() {return this};
}
This one fails with a compilation error ("unexpected token: public at line: 5, column: 4")
println 0;
class myClass
{
public myClass(int j) {};
public myClass method() {return this};
}
The only difference is the capitalization of the class name. I know the convention is for class names to be capitalized, but I thought it was just a convention. What exactly causes the compile error?
According to a Groovy mailing list thread from 2008, where a similar question was posed, Paul King explained:
Yes, the grammar currently looks for uppercase types only in declarations (apart from the primitive types).
In a more recent, unresolved Groovy JIRA ticket regarding lowercase class names, blackdrag comments that:
The problem is that in Groovy (unlike Java) variable names, method names and class names can share a context, making it ambiguous.
Barring a deeper exploration of the tokenizer, I'll just chalk this up as another minor inconsistency between Java and Groovy due to Groovy's syntax flexibility. And instead of thoroughly implementing a way to tell if a token is a type or method name in this context, Groovy takes a short cut and only assumes it can be a type name if the token matches a primitive or begins with a capital letter, as conventional Java types would.
I call an overloaded method (assertThat) which has one signature with a BigDecimal parameter and another one with double primitive parameter.
When I launch this snippet in groovy, it calls the one with BigDecimal parameter when I was expecting the double primitive parameter one to be called.
double[] erreur = Seg.erreur(xtab, ytab, 0, 2)
Assertions.assertThat(erreur[1]).isEqualTo(-0.3333333333333333)
Can someone explain me why ?
Thanks in advance.
By default, a decimal number in groovy is a BigDecimal. If you want it to be a double, you should use the suffix D or d:
From Number type suffixes in the docs:
assert 123.45 == new BigDecimal('123.45') // default BigDecimal type used
assert 1.200065D == new Double('1.200065')
Your isEqualsTo() is passing a BigDecimal as parameter, whereas your assertThat() is passing a double. Just add a d at the end of that -0.3333333333333333 and it should work:
import static org.assertj.core.api.Assertions.assertThat
class Doubles extends GroovyTestCase {
void testAssertions() {
double[] erreur = [0.1, -0.3333333333333333, 0.3]
assertThat(erreur[1]).isEqualTo(-0.3333333333333333d)
}
}
What kind of type coercion does groovy support?
I saw map coercion and closure coercion. Are there any other?
And what is the difference between type coercion and type inference?
For example
def i = 1000 // type infere to Integer
i = 1000000000000 // type infere to Long or is this type coercion?
Groovy can use dynamic untyped variables whose types are assigned at runtime. Type inference refers to the automatic deduction of the type of an expression.
In your example: def i = 1000 assigns an instance of java.lang.Integer to the variable
Few simple tests as examples:
assert "Integer" == 1000.class.simpleName
assert "Long" == 1000000000000.class.simpleName
assert "BigDecimal" == 3.14159.class.simpleName
assert "Float" == 3.14159f.class.simpleName
According to Groovy's documentation: "Closures in Groovy work similar to a "method pointer", enabling code to be written and run in a later point in time".
Also, when working on Collections of a determined type, the closure passed to an operation on the type of collection can be inferred.
Type coercion is in play when passing variables to method of different type or comparing variables of different types. In comparing numbers of different types the type coercion rules apply to convert numbers to the largest numeric type before the comparison. So the following is valid in Groovy.
Byte a = 12
Double b = 10
assert a instanceof Byte
assert b instanceof Double
assert a > b
The Groovy "as" keyword is used in following situations:
used for "Groovy" casting to convert of value of one type to another
used to coerce a closure into an implementation of single method
interface
used to coerce a Map into an implementation of an interface, abstract, and/or concrete class
In addition to type coercion in maps and closures, there is also "Groovy Truth", which evaluates a type in an expression as TRUE or FALSE.
null is false
empty String, Map, or Collection is false
Zero number is false
if ( list ); if ( string ), if ( map )
same as writing if (list != null && !list.isEmpty()) ...
References:
Static Groovy and Concurrency: Type Inference in Action
http://groovy.dzone.com/articles/static-groovy-and-concurrency-3
Groovy Operator Overloading
http://groovy.codehaus.org/Operator+Overloading