20

Should we or should we not define the datatype of a variable or return type of a method if we know the datatype and also it is not going to change at runtime? What are the pros and cons or using def vs actual datatype?

One example being, if abc is intended to be List<String>

List<String> abc = "xyz"; //IntelliJ IDEA gives syntax highlighting for improper assignment
def abc = "xyz"; //IntelliJ IDEA will not give syntax highlighting
Szymon Stepniak
  • 40,216
  • 10
  • 104
  • 131
Shikhar
  • 357
  • 1
  • 3
  • 12
  • The official Groovy documentation has some suggestions on when to use which: https://groovy-lang.org/style-guide.html#_optional_typing_advice – Koray Tugay Jul 26 '21 at 00:42
  • Does this answer your question? [Explicit typing in Groovy: sometimes or never?](https://stackoverflow.com/questions/2262092/explicit-typing-in-groovy-sometimes-or-never) – Alberto May 31 '22 at 10:08

2 Answers2

23

It's easy to fall into the trap of using def everywhere, due to convenience (especially if coming from Java)

But as you have seen, if you know the type of something, it's better to type it, especially on public methods. Benefits include; self documentation, ide hints, sanity...

tim_yates
  • 167,322
  • 27
  • 342
  • 338
16

def ~= Object

As Tim pointed out, def is not a an alias to Object data type, but it can be though as one (Object is a class while def is just a Groovy keyword) - http://www.groovy-lang.org/semantics.html#_variable_definition The only thing def has in common with Object is the fact that on the JVM level every def statement or type replacement is compiled to Object,

Consider very simple test.groovy script with following content:

def name = "John"

String surname = "Doe"

println "$name $surname"

If you compile it to test.class and take a look at the decompiled code here is what you will see:

Compiled from "test.groovy"
public class test extends groovy.lang.Script {
  public static transient boolean __$stMC;

  public test();
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          4       4     0  this   Ltest;

  public test(groovy.lang.Binding);
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       9     0  this   Ltest;
          0       9     1 context   Lgroovy/lang/Binding;

  public static void main(java.lang.String...);
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      19     0  args   [Ljava/lang/String;

  public java.lang.Object run();
    LineNumberTable:
      line 1: 4
      line 3: 9
      line 5: 14
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      63     0  this   Ltest;
          7      56     2  name   Ljava/lang/Object;
         12      51     3 surname   Ljava/lang/String;

  protected groovy.lang.MetaClass $getStaticMetaClass();
}

IDE syntax support

If you use IDE that supports Groovy well (e.g. IntelliJ IDEA) then you should be able to make usage of type inference and IDE would provide you a syntax support.

Purpose of def keyword

The main purpose of def is to introduce dynamic types in Groovy. As you can see in the above example, this is still old Java Object type.

The good practice is to use static types whenever you use static type on purpose. Your public API should definitely use static types for documentation reasons. I personally use def from time to time in two cases:

  • in local variables that has very limited scope and variable name provides all information about the variable itself
  • in Spock unit tests in test case name e.g. def "should do something"() { }
The Alchemist
  • 3,397
  • 21
  • 22
Szymon Stepniak
  • 40,216
  • 10
  • 104
  • 131