Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

adding a custom constructor without losing the default map constructor

By default every Groovy class has a Map constructor, e.g.

class Foo {
  def a
  def b
}

// this works
new Foo(a: '1', b: '2')

However, it seems that as soon as you add a constructor of your own, this default constructor is not available

class Foo {

  Foo(Integer x) {
    println 'my constructor was called'  
  }

  def a
  def b
}

// this works
new Foo(1)

// now this doesn't work, I get the error: groovy.lang.GroovyRuntimeException: 
// failed to invoke constructor
new Foo(a: '1', b: '2')

Is it possible to add your own constructor without losing the default map constructor? I tried annotating the class with @TupleConstructor but it made no difference. I realise I could add the map constructor myself, e.g.

public Foo(Map map) {    
  map?.each { k, v -> this[k] = v }  
}

Though the constructor above is not identical to the default map constructor because a key in the map that does not have a corresponding property in the class will cause an exception.

like image 763
Dónal Avatar asked Oct 14 '14 13:10

Dónal


People also ask

Does STD map require default constructor?

The default constructor is not required.

When a new object is created in a program a constructor gets invoked corresponding to the class?

When is a Constructor called? Each time an object is created using a new() keyword, at least one constructor (it could be the default constructor) is invoked to assign initial values to the data members of the same class.

Can we override default constructor in Java?

Constructor looks like method but it is not. It does not have a return type and its name is same as the class name. But, a constructor cannot be overridden. If you try to write a super class's constructor in the sub class compiler treats it as a method and expects a return type and generates a compile time error.

Is it mandatory to have default constructor?

The compiler doesn't ever enforce the existence of a default constructor. You can have any kind of constructor as you wish. For some libraries or frameworks it might be necessary for a class to have a default constructor, but that is not enforced by the compiler.

What happens if you don’t provide a constructor for a class?

If you don’t provide a constructor for your class, C# creates one by default that instantiates the object and sets member variables to the default values as listed in the Default Values Table. Constructor without any parameters is called a default constructor. In other words, this type of constructor does not take parameters.

What is a constructor without any parameters called?

Constructor without any parameters is called a default constructor. In other words, this type of constructor does not take parameters. The drawback of a default constructor is that every instance of the class will be initialized to the same values and it is not possible to initialize each instance of the class to different values.

What is Map () constructor in Java?

The Map () constructor creates Map objects. An Array or other iterable object whose elements are key-value pairs. (For example, arrays with two elements, such as [ [ 1, 'one' ], [ 2, 'two' ]] .)

What are the disadvantages of a default constructor?

The drawback of a default constructor is that every instance of the class will be initialized to the same values and it is not possible to initialize each instance of the class to different values. All numeric fields in the class to zero.


1 Answers

If you are on Groovy 2.5 or later, you can apply the @MapConstructor annotation.

@groovy.transform.MapConstructor
class Foo {
    def a, b
    Foo(Integer x) {
        println 'my constructor was called'
    }
}

// this works
new Foo(1)

// the map constructor is present, too
def mappedFoo = new Foo(a: '1', b: '1')
assert mappedFoo.a == '1'
assert mappedFoo.b == '1'

If you're using an older version of Groovy, the @InheritConstructors annotation can be used as a substitute for @MapConstructor, but as Arie pointed out, avoid this approach if you're class extends some base class; if the base class lacks a no-arg constructor this will not work.

like image 190
bdkosher Avatar answered Oct 01 '22 19:10

bdkosher