red888
red888

Reputation: 31684

How can I use named parameters AND prevent the default constructor from being used?

I'm confused about how to accomplish this in the cleanest most Groovy way, but I can't figure out how to do it at all first

I just want to force that when a class is created all its constructor args be set:

class MyClass {
  String paramOne
  String paramTwo

  MyClass(paramOne, paramTwo) throws Exception {
    this.paramOne = paramOne
    this.paramTwo = paramTwo
  }

}

// I want to throw an error if all the constructor args arent set
// This doesnt throw an error
MyClass blah = new MyClass()

Upvotes: 0

Views: 385

Answers (2)

Jeff Scott Brown
Jeff Scott Brown

Reputation: 27255

// This doesnt throw an error MyClass blah = new MyClass()

That does not make sense. That should throw an error.

See the project at https://github.com/jeffbrown/red888.

app/src/main/groovy/red888/MyClass.groovy

package red888

class MyClass {
    String paramOne
    String paramTwo

    MyClass(paramOne, paramTwo) throws Exception {
        this.paramOne = paramOne
        this.paramTwo = paramTwo
    }

}

app/src/main/groovy/red888/App.groovy

package red888

class App {
    static void main(String[] args) {
        //  groovy.lang.GroovyRuntimeException: Could not find matching constructor for: red888.MyClass()
        MyClass blah = new MyClass()
    }
}

That throws the expected exception.

~ $ mkdir demo
~ $ cd demo
demo $ git clone [email protected]:jeffbrown/red888.git
Cloning into 'red888'...
remote: Enumerating objects: 25, done.
remote: Counting objects: 100% (25/25), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 25 (delta 3), reused 25 (delta 3), pack-reused 0
Receiving objects: 100% (25/25), 60.11 KiB | 1.11 MiB/s, done.
Resolving deltas: 100% (3/3), done.
demo $ 
demo $ cd red888
red888 (main)$ 
red888 (main)$ ./gradlew run

> Task :app:run FAILED
Exception in thread "main" groovy.lang.GroovyRuntimeException: Could not find matching constructor for: red888.MyClass()
        at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1845)
        at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1615)
        at org.codehaus.groovy.runtime.callsite.MetaClassConstructorSite.callConstructor(MetaClassConstructorSite.java:46)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:268)
        at red888.App.main(App.groovy:6)

FAILURE: Build failed with an exception.

Upvotes: 0

daggett
daggett

Reputation: 28634

question from the comment:

Is there a way I can use named parameter and prevent the default constructor for being used?


@groovy.transform.ToString
class A{
    String p1
    int p2
    
    A(Map params=null){
        assert params:"at least one parameter is required for ${this.getClass()}"
        A.metaClass.setProperties(this,params)
        //validate params...
        assert p1:'`p1` couldn\'t be empty'
    }
}

A a=new A(p1:111,p2:222)
println a

new A() // <<<--- this throws exception

Upvotes: 1

Related Questions