Confusion about fileds and get methods in Kotlin - kotlin

Since A is a property and not a field, does that mean that A and B are functioning exactly the same way? If not, what are their difference?
class myClass(val x : Int, val y : Int){
val A = x * y
val B :Int
get(){
return x * y
}
}

In this specific example, a property with a backing field (A) and a property without a backing field (B) work exactly the same, because x and y are vals and their values can't be reassigned - no matter how many times you compute x * y it'll always return the same result. But consider the following program:
class myClass(var x : Int, val y : Int){
val A = x * y
val B :Int
get(){
return x * y
}
}
fun main() {
val myClass = MyClass(x = 2, y = 3)
println(myClass.A) // 6
println(myClass.B) // 6
myClass.x = 4
println(myClass.A) // 6
println(myClass.B) // 12
}
x is a var now, which means that its value can be changed. The value of A has already been computed when the instance of MyClass was created, so changing the value of x has no effect on the value of A. But since accessing B executes the body of its getter every time, a change in the value of x will affect the result of the next call to that getter.

Related

Best way to hide internal classes by interfaces

what is the best way to hide an impl class behind an interface?
The companion creator works well, but needs to repeat all the arguments of the constructor twice.
Is there a way to simplify A.from(x,y,z,a,b,c,d) = AImpl(x,y,z,...)?
//the application will only see this interface
interface A {
val x: X
val y: Y
companion object {
//choose any implementation without breaking existing code
#JvmStatic
fun from(x: X, y: Y): A = AImpl(x = x, y = y) //inconvenient for many arguments
}
}
internal class AImpl(
override val x: X,
override val y: Y
) : A
fun someApplication() {
val a = A.from(..., ...) //no reference to AImpl
//use a: A
}
Thank you very much.
Martin
The way you wrote it is already good. If you're concerned about too many parameters, note that you don't have to name and pass every single one of them, and not every property needs to be passed as a constructor parameter. Depending on the implementation class, some properties can be defaulted or calculated:
interface A {
val x: X
val y: Y
companion object {
fun from(x: X, y: Y): A = AImpl(x)
}
}
internal class AImpl(
override val x: X,
) : A {
override val y = something()
}
Furthermore, AImpl doesn't have to be internal; it can be private or even an anonymous class, if it's a very short one (otherwise the code can become unreadable):
interface A {
val x: X
val y: Y
companion object {
fun from(x: X, y: Y): A = object : A {
override val x = x
override val y = y
}
}
}
Instead of using a member function of a companion object, a common Kotlin-idiomatic way is to use a standalone factory function with the same name as the interface:
fun A(x: X, y: Y): A = AImpl(x, y)
An example of such a function is MutableList: it has the same name as interface MutableList, and it happens to return an ArrayList but that's just implementation detail: it's only documented to return something that implements interface MutableList.
I don't really understand what are you tring to do.
So i'm not sure if this will be the answer to your question.
fun main() {
val x = X()
val y = Y()
val a = AImpl().from(x,y)
a.x.toString()
a.y.toString()
//use object class so you can use the class without ()
val b = BImpl.from(x,y)
b.x.toString()
b.y.toString()
}
class X{}
class Y{}
interface A
{
val x : X
val y : Y
fun from(xValue : X, yValue : Y) : A
}
internal class AImpl() : A {
override var x : X = X()
override var y : Y = Y()
override fun from(xValue : X, yValue : Y) : A {
x = xValue
y = yValue
return this
}
}
object BImpl : A {
override var x : X = X()
override var y : Y = Y()
override fun from(xValue : X, yValue : Y) : A {
x = xValue
y = yValue
return this
}
}
I don't think you should implementation anything in Interface
but If you want your code to work
companion object {
//choose any implementation without breaking existing code
#JvmStatic
//fun from(x: X, y: Y): A = AImpl(x = x, y = y)
//because you Return A That's why you got no reference to AImpl
//so don't return A but make it AImpl directly
//but it's still act like "A" interface.
fun from(x: X, y: Y) = AImpl(x,y)
}
}

Variables in Standard ML change if a new function declaration,was apllied by using the changed variable

See the following code where I tried out how already been declared variable x acts after being newly bound and then used within a function declaration. Why it is acting like this?
- val x = 2;
val x = 2 : int
- fun addx y = y + x;
val addx = fn : int -> int
- addx(5);
val it = 7 : int
- val x = 5;
val x = 5 : int
- addx(5);
val it = 7 : int
- subx y = y - x;
- fun subx y = y - x;
val subx = fn : int -> int
- subx(7);
val it = 2 : int
- 3 + x;
val it = 8 : int
- addx(10);
val it = 12 : int
This is caused by a combination of two features: immutability and variable shadowing. Variables are immutable, and cannot be reassigned to new values. But SML does allow you to shadow variable bindings, meaning that you are allowed to reuse an existing variable name for a new purpose (within a new lexical scope).
In the code you wrote, you used the name x twice for two different variables. The second declaration of x shadows the first, i.e., any code in the lexical scope that follows which mentions x is referring to the new declaration, not the old one. (Because of this possible confusion, some people consider variable shadowing to be bad code style.)
We can rename the second declaration to make everything much clearer:
- val x = 2;
val x = 2 : int
- fun addx y = y + x;
val addx = fn : int -> int
- addx(5);
val it = 7 : int
- val DIFFERENT_VARIABLE = 5;
val DIFFERENT_VARIABLE = 5 : int
- addx(5);
val it = 7 : int
- fun subx y = y - DIFFERENT_VARIABLE;
val subx = fn : int -> int
- subx(7);
val it = 2 : int
- 3 + DIFFERENT_VARIABLE;
val it = 8 : int
- addx(10);
val it = 12 : int

How to define function, which accepts all numerics in Kotlin

What I thought didn't work
fun compute1(x: Double, y:Double) : Double {
return x + y
}
fun compute2(x: Number, y:Number) : Number {
return x + y // can't use plus
}
fun main() {
compute1(12, 13) // cant use integers
}
How to accomplish?
Solution should be as laconic as in java
public class MathEx {
public static double compute(double x, double y) {
return x+y;
}
}
You could overload the function to receive the combinations that you want
fun compute(x:Double, y:Double) = x + y
fun compute(x:Float, y:Float) = x + y
fun compute(x:Int, y:Int) = x + y
fun compute(x:Double, y:Int) = x + y
fun compute(x:Float, y:Int) = x + y
fun main() {
compute(12, 13)
}
Quite verbose, or you can define just one or two and convert the number before calling the function, which is not very efficient but it would work
fun compute(x:Double, y:Double) = x + y
fun main() {
compute(12.toDouble(), 13.toDouble())
}
from https://kotlinlang.org/docs/basic-types.html#floating-point-types
Note that unlike some other languages, there are no implicit widening conversions for numbers in Kotlin. For example, a function with a Double parameter can be called only on Double values, but not Float, Int, or other numeric values.
It's not a perfect solution since there are examples where you get rounding errors but for your use case this might be good enough
fun compute2(x: Number, y:Number) : Double{
return x.toDouble() + y.toDouble()
}

How to get new variable value from inherited class?

open class Parent(){
protected var z : Int? = null
private fun getMyAge(){
val x = 65
val y = 10
z = x % y
}
}
class Child:Parent(){
ovveride fun getMyAge()
println(z) //here I get null
}
My question is: why I get null?
Am I getting a variable from an inherited class incorrectly?
It's because when you override the function, the super function is not called. If you want the function in parent class called, you must change your code to this:
open class Parent(){
protected var z : Int? = null
private fun getMyAge(){
val x = 65
val y = 10
z = x % y
}
}
class Child:Parent(){
ovveride fun getMyAge()
super.getMyAge()
println(z)
}

Assign 2 vals in class init block using function which returns Pair

Given a class like this:
class Test {
val A: Car
val B: Truck
init {
(A, B) = returnCarAndTruck()
}
fun returnCarAndTruck() = Pair(Car(), Truck())
}
I want to intialize the vals for A and B using a function which returns a pair but it doesn't seem to work unless I define the vals inside the init block. This means I no longer have reference to them correct? Is it possible to intialize these 2 with a Pair?
The best we have for what you're looking for is the following:
class Test {
val A: Car
val B: Truck
init {
val (a, b) = returnCarAndTruck()
A = a
B = b
}
fun returnCarAndTruck() = Pair(Car(), Truck())
}