0

I want to be able to write that calls a factory method to create an instance of a object instead of directly calling the constructor.

I have a factory named, PersonFactory that implements a method called getPresonTypeOne(name: String, age:Int, address: String). PersonTypeOne has three member variables named name, age, and address. I want to be able to write something that calls getPresonTypeOne to create an instance of PersonTypeOne instead of directly calling the PersonTypeOne constructor.

I ideally what something that looks like this

class PersonTypeOne(
      val name: String, 
      val age: Int, 
      val address: String) {
    ...
}


personTypeOne {
    withName {
       ...
    }
    withAge {
       ...
    }
    withAddress {
       ...
    } 
}

I would like that DSL to get effectively result in a call that looks like this : personFactory.getPresonTypeOne(name, age, address)

I have looked around quite a bit, but I have only found examples of me being able to do this by directly calling the PersonTypeOne constructor.

1 Answers1

1

I am not sure, what your indent is. If you only want to hide the factory call, you don't need a DSL. A function with named parameter will do the job:

fun personTypeOne(name: String, age: Int, address: String): PersonTypeOne =
    PersonFactory.getPersonTypeOne(name, age, address)

val person1 = personTypeOne(name = "Name", address = "address", age = 42)

If you really need a DSL, you need to define a builder helper class with methods for each attribute and a function to use this builder:

class PersonTypOneBuilder {
    private var name: String? = null
    private var age: Int? = null
    private var address: String? = null

    fun withName(name: () -> String) {
        this.name = name()
    }

    fun withAge(age: () -> Int) {
        this.age = age()
    }

    fun withAddress(address: () -> String) {
        this.address = address()
    }

    fun build() =
        PersonFactory.getPersonTypeOne(
            name ?: throw IllegalStateException(),
            age ?: throw IllegalStateException(),
            address ?: throw IllegalStateException()
        )
}

fun personTypeOne(block: PersonTypOneBuilder.() -> Unit): PersonTypeOne =
    PersonTypOneBuilder().apply(block).build()

Now you can use the DSL:

val person2 = personTypeOne {
    withName {
        "Bla"
    }
    withAddress {
        "address"
    }
    withAge {
        42
    }
}
Rene
  • 5,730
  • 17
  • 20
  • @jadeblack12 Then the second solution should work. Look at the documentation for [type safe builders](https://kotlinlang.org/docs/reference/type-safe-builders.html). But you should be aware, that you have to create the builder classes and methods by yourself. Or do you see a problem with the second solution? – Rene Feb 01 '19 at 11:01
  • Yes, I believe the second solution works as well (testing it right now), but I was really hoping there was a way to achieve this without a builder. Will mark the answer as approved in a bit after testing as this does look like it solves my problem. – jadeblack12 Feb 01 '19 at 11:08
  • I was able to do exactly what I wanted with this. – jadeblack12 Feb 01 '19 at 12:39