Is it possible to destructure data class' instance into class' properties? - kotlin

I have a data class MyDataClass:
data class MyDataClass(val a: Int, val b: Int)
and a class MyClass with two properties. I want to destructure an instance of MyDataClass, so a and b are assigned to MyClass properties, instead of declare new variables:
class MyClass {
val a: Int
val b: Int
init {
val mdc = MyDataClass(1, 4)
(a, b) = mdc //error
}
}

No, destructuring declarations are only allowed for local variables and lambda parameters.
Also, they are only used to create multiple local variables at once. So val (a, b) = mdc is allowed, but
(a, b) = mdc is invalid syntax, even if a and b are not properties.

Although destructuring declaration are only allowed for local you can still do something like this
class MyClass {
val a: Int
val b: Int
init {
val (a, b) = MyDataClass(1, 4)
this.a = a
this.b = b
}
}

Related

Destructuring props passed to functional component in kotlin

In JavaScript, the destructuring of an object is something common.
const foo = {
a: 1
b: 2
c: 3
};
const {a, b, c } = foo;
console.log(a)
1
Is something like this possigle with KotlinJS React?
interface FooProps : Props {
var a: Int
var b: Int
var c: Int
}
val Foo = FC<FooProps> { props ->
val(a, b, c) = props
...
}
This is not working. It gives me
Destructuring declaration initializer of type FooProps must have a 'component1()' function
Kotlin supports destructuring declarations, however they work in a different way than JavaScript.
In particular, you can destructure an object like this:
val (property1, property2, property3, ..., propertyN) = object
assuming that object contains certain methods:
operator fun component1()
operator fun component2()
...
operator fun componentN()
Example:
class Person(val name: String, val dateOfBirth: LocalDate) {
operator fun component1(): String = name
operator fun component2(): LocalDate = dateOfBirth
}
val johnDoe = Person("John", LocalDate.of(1980, JANUARY, 1))
val (name, dob) = johnDoe
println("$name -> $dob") // prints John -> 1980-01-01
Use can make use of extension functions to implement this behaviour on classes you don't own. Example:
operator fun String.component1(): Int = this.length
operator fun String.component2(): Char = this.first()
val someString = "Hello, world"
val (length, firstChar) = someString
println("$length -> $firstChar") // prints 12 -> H

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())
}

Kotlin allows defining data class in a function, why?

In kotlin, this is legal:
fun f1(): Int {
data class Data(val i: Int)
val d = Data(0)
return d.i
}
I wonder what are the consequenses of declaring a data class in a function. My best guess is that the data class is scoped to the function but I do not find anything in the doc mentionning that.
This is called Local Classes. They are mentioned in the documentation but only that they cannot have visibility modifiers.
You cannot access local class anywhere outside of the function it was declared in.
It can access any members, including private members, of the containing class.
It can access any local variables or method parameters that are in the scope of the declaring function
You can take a look at Java's local classes for more information. It should be basically the same.
A typical use case is to have a throw-away implementation of some interface.
fun main() {
val f1 = f1()
println(f1.x)
println(f1.y)
}
interface Data {
val x : Int
val y : Int
}
fun f1(): Data {
data class SpecificData(override val x: Int, override val y: Int) : Data
return SpecificData(5, 10)
}

Object expressions, Multiple supertype specification syntax?

I am new to Kotlin. I came across the Object Expressions section of https://kotlinlang.org
Some of the object expression syntaxes are very straight forward to understand,
Create an object of an anonymous class
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) { ... }
override fun mouseEntered(e: MouseEvent) { ... }
})
Just an object
fun foo() {
val adHoc = object {
var x: Int = 0
var y: Int = 0
}
print(adHoc.x + adHoc.y)
}
But I am unable to understand the "Object expression with multiple supertypes specified" example given as below:
open class A(x: Int) {
public open val y: Int = x
}
interface B { ... }
val ab: A = object : A(1), B {
override val y = 15
}
What's happening here?
${ab.y} prints 15
but syntax -> ${ab.A.y} is not valid. My understanding of ${ab.A.y} it will print 1 :)
This line here:
val ab: A = object : A(1), B {
means that the class of ab is inherited from class A and implements interface B.
Actually the code example you gave will only compile if you declare and implement the interface. This is a possible implementation:
open class A(x: Int) {
public open val y: Int = x
}
interface B {
fun hi()
}
val ab: A = object : A(1), B {
override val y = 15
override fun hi() {
println("hi")
}
}
The expression ${ab.A.y} does not make much sense in this context, because the object ab does not have any field A. A is just the inherited superclass to which you could eventually cast.
It basically creates object ab with class type A with implementation of interface B.
So, let's say your class A has some method foo() & interface B has some method bar(), you can access them both on object ab as it's of class type A with implementation of B.
Hence, here you override variable y with value 15 meaning your superclass variable y will get overridden by value 15 from 1.

What is the difference between these ways for defining functions?

I am from a background of Javascript trying to learn some Kotlin.
I know i can define my function by
fun add(a: Int , b: Int): Int{
return a+b
}
I am trying this
val add = {
a:Int,b:Int->
println("I am calculating the sale => no body you guy [$x+$y]");
//works
}
val add = { a:Int ,b : Int ->
//How do i return from this function
}
Also Is this a right way to define Kotlin functions? and Whats the difference with the first way ?
Also Is this a right way to define Kotlin functions? and Whats the difference with the first way ?
This is not even "a way to define Kotlin functions".
In JavaScript, all functions are reified: they are first-class values you can refer to from variables and pass around. Not so in Kotlin, just as in many other languages like Java, C++, Objective C and so on.
A function is just a declaration, you can call it but you can't otherwise directly refer to it. Separate language features allow you to create functional objects that delegate to these functions, and you can pass these objects around.
Therefore,
fun add(a: Int , b: Int): Int {
return a + b
}
is a function declaration and
val add = {a: Int, b: Int ->
a + b
}
is four things:
declaration of a variable add
declaration of an anonymous implementation of the functional type (Int, Int) -> Int
instantiation of this anonymous type, resulting in a functional object
assignment of the object to the variable add.
The object has a method invoke(a: Int, b: Int): Int whose implementation you have given in the block:
fun invoke(a: Int, b: Int): Int {
return a + b
}
You can call it explicitly:
val result = add.invoke(a, b)
and on top of that Kotlin defines syntax sugar that allows you to omit the explicit .invoke.
You don't need the explicit return there
val add = { a: Int, b: Int ->
a + b
}
add(2, 3) // => 5
Hopefully this will work.
val onChange = {
a:Int,b:Int->
println("I am calculating the sale => no body you guy [$x+$y]");
//works
}
val add = { a:Int ,b : Int ->
println("Sunm ${a+b}")
//How do i return from this function
}
Log.v("Response", add(4,3))
Output
V/Response: Sum 7
You can't return values in kotlin like this, it will give error of type mismatch as you havn't declared any return type :
fun add(a: Int , b: Int){
return a+b
} //wrong
we declare return type in kotlin as :
fun add(a: Int , b: Int) : Int{
return a+b
}
Secondly,
val add = { a:Int ,b : Int ->
}
this is not a function, its a declaration of value assignment
In kotlin we declare function by adding "fun" before your function name as
//you can add access modifiers(private,public,protected) if needed just before "fun"(by default its public)
fun add (){ //if it returns any value then add ": {datatype}" just right of "()"
//your code here
}
Hope it helped you :)