Calculating the field that is not presented in constructor

Related searches

Let's say I have a class with 3 fields: A, B, and C. I can create an instance of this class in two ways: pass all fields to the constructor, or pass only A and other properties will be calculated based on A.

class MyClass {
    val A: String
    val B: String
    val C: String

    constructor(A: String, B: String, C: String) {
        this.A = A
        this.B = B
        this.C = C
    }

    constructor(A: String) {
        this.A = A
        val (_B, _C) = Calculator.calculate(A)
        this.B = _B
        this.C = _C
    }
}

This approach uses two secondary constructors without primary one. But from my point of view, it looks pretty heavy. Is it possible to rewrite this logic in a more elegant way?

Maybe something as follows might be ok for you. You may want to replace Pair with an actual type then instead...

class MyClass(
        val A: String,
        val BC : Pair<String, String>
) {
    constructor(A: String, B: String, C: String) : this(A, B to C) // is this then even needed?
    constructor(A : String) : this(A, Calculator.calculate(A))
}

Or alternatively if it makes more sense to have the three separate properties, the other way around, which was also shown by k0enf0rNL :

class MyClass(
     val A: String,
     val B: String,
     val C: String
) {
  constructor(A: String) : this(A, Calculator.calculate(A))
  constructor(A: String, BC : Pair<String, String>) : this(A, BC.first, BC.second)
}

Finally, if you do not want to expose some of the constructors, feel free to mark them private, e.g. the following will expose the same as your shown example:

class MyClass(
     val A: String,
     val B: String,
     val C: String
) {
  constructor(A: String) : this(A, Calculator.calculate(A))
  private constructor(A: String, BC : Pair<String, String>) : this(A, BC.first, BC.second)
}

Maybe you rather need something to pass a function instead (as you also used Calculator.calculate(A)). Then you may want to add the following as a constructor:

constructor(A : String, func: (String) -> Pair<String, String> = Calculator::calculate) : this(A, func(A))

If this is rather what you wanted from the beginning, then even a class such as the following might be something for you:

class MyClass(val A: String,
              func: (String) -> Pair<String, String> = Calculator::calculate) {
    val B: String
    val C: String

    init {
        func(A).also { (newB, newC) ->
            B = newB
            C = newC
        }
    }
}

If you then just want to pass A, B and C without an actual calculation (or passed function), you can still do it as follows (basically discarding the passed A):

MyClass("myA") { /* _ -> */ /* A -> */
   "myCalculatedB" to "C"
}

Java Constructors, Java constructors can also take parameters, so fields can be initialized in the object at creation time. They determine what classes can access (call) the constructor. Also notice that the constructor has no return type, like other methods have. The field is thus initialized to the given parameter value. The 1st field can be set very easily. To fill the 2nd field, we take the 1st field's content and calcuate a lot. The 3rd, 4th and 5th field must be calculated together from field1 and field2 (it is not possible to calculate 3, 4 and 5 isolated from each other without severe performace loss). And the 6th field is calculated from field 1, 3 and 4.

My personal favourite is to abuse companion object invoke operator:

class MyClass(val A: String, val B: String, val C: String) {

    companion object {
        operator fun invoke(A: String): MyClass {
            val (B, C) = Calculator.calculate(A)
            return MyClass(A, B, C)
        }
    }
}

Finding Constructors (The Java™ Tutorials > The Reflection API , for accessing and manipulating classes, fields, methods, and constructors. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. I was wondering if it is possible in java to access the fields of the object from one of its own fields that is an object itself. Let me present a sample code: Suppose I have a class (I am condensing the code here, so I know the presented code will not compile)

You could write it as a data class and at least get rid of the default constructor like so

data class MyClass(
    val A: String,
    val B: String,
    val C: String
) {
    constructor(A: String, calculated: Pair<String, String> = calculate()) : this(
        A,
        calculated.first,
        calculated.second
    )
}

fun calculate() : Pair<String, String> = "this" to "that"

Constructors in Java, A constructor in Java can not be abstract, final, static and If we want to initialize fields of the class with your own values, then you want to share more information about the topic discussed above. Program to calculate Electricity Bill � Count of Ordered Pairs (X, Y) satisfying the Equation 1/X + 1/Y = 1/N� method not calculating and constructor not initializing? I'm working on a problem out of my text book, and when I run my program, it does not compute the GPA, even though I have a method to do so, and I do not think my constructor is initializing.

Writing a good/readable constructor that needs a lot of calculation to , Also, since the calculation methods are going to be private, the compiler may even optimize them away, so there may even be no performance� Recently I saw people doing the initialization directly, so without setting the value in the constructor. public class Test { private int myIntToInitalize = 10; } In point of view, there is not difference whether initialize and declare a variable or initialize the variable in the constructor.

Java - parameterized constructor with example, As we discussed in the Java Constructor tutorial that a. During object creation the parameters we pass, determine which constructor should get invoked for object initialization. While discussing default constructor, we have seen that when we do not create a default constructor, Java Required fields are marked * . Default Constructor: Each time an object is created, a constructor is always invoked. But in some programs if we don’t create any constructor. So in such situations, the compiler automatically creates one constructor which is known as default constructor. It does not contain any parameters and doesn’t even contain any statements in its body.

If a superclass does not have a default constructor or a no-arg constructor: A) then a class that inherits from it, does not inherit the data member fields from the superclass. B) then a class that inherits from it, must call one of the constructors that the superclass does have.

Comments
  • what does calculate return? as it is destructurable, may the same type be OK in MyClass itself?
  • It returns Pair<String, String>
  • I only dislike the word "abuse" here ;-) what I like on that variant is, that you can easily move such functions outside the class using extension functions on the Companion, which therefore also easily allows adding additional variants...
  • I would even use a direct assignment for the invoke... it doesn't do that much, so you can still easily grasp it, e.g.: operator fun invoke(A: String) = Calculator.calculate(A).let { (B, C) -> MyClass(A, B, C) } (new lines where appropriate)
  • @Roland I though of it, even already edited my answer but discarded. In the general case there could be more than just one external calculation, and things could get ugly with .let version.
  • My mistake, I messed up the constructor implementation. Fixed it now.
  • regarding your comment in the answer: I don't think so... but you can still add an additional constructor for that, e.g.: constructor(A: String, BC : Pair<String, String>) : this(A, BC.first, BC.second)
  • Whether it's a data class isn't really relevant here.