Is it possible to access parent object from within its lambda property? - kotlin

I need to access the instance of a class from inside the function stored in its constructor property, like this
data class Parent(
val lambda: () -> Unit = {
// I need the instance of the enclosing Parent here
// this#Parent doesn't work
}
)
Is this possible?

It really depends on what you want to do with the lambda. If you do not need to access this in order to access any private members of the class, you could define the lambda as a receiver function which is then called with the newly created object in the constructor or init block like this:
data class Parent(
val lambda: Parent.() -> Unit
) {
init {
this.lambda()
}
}
Then you can use this in the lambda that is a parameter of the constructor like this:
fun main() {
val list = mutableListOf<Parent>()
val parent = Parent { list.add(this) } // parent has been added to list on creation
}
However, as mentioned above, you cannot use this to break up the encapsulation of the class, e.g. if there is a private member x defined inside Parent, you cannot call this.x, but only publicly accessible members.

No, this isn't possible because the Parent object doesn't exist at the point when the lambda is created. The lambda is being passed as an argument to the constructor that will create the object, so the lambda has to be created first.
If the lambda was created inside the class instead of being passed to the constructor, you would be able to use this to access the containing object.

make the constructor method private and create a static factory method then you can create the parent and the chield objects and then inject the reference. After that, you can access them as you wish.

Related

Can I add Kotlin extension function to Java class?

I'm trying to create extension function like this:
fun UHFTAGInfo.toReadUhfTagInfo(): ReadUhfTagInfo {
return ReadUhfTagInfo(this.epc, this.count, this.rssi.toIntOrNull())
}
It is supposed to convert UHFTAGInfo (from java library) to ReadUhfTagInfo (my class in Kotlin).
I'm trying to use it like this:
UHFTAGInfo i = getUHFTAGInfo();
ReadUhfTagInfo ri = i.toReadUhfTagInfo();
At this moment my toReadUhfTagInfo function is at top level, but finally I want to put it in my ReadUhfTagInfo class, like this:
class ReadUhfTagInfo(var epc: String, var cnt: Int, var rssi: Int?)
{
fun UHFTAGInfo.toReadUhfTagInfo(): ReadUhfTagInfo {
return ReadUhfTagInfo(this.epc, this.count, this.rssi.toIntOrNull())
}
}
You can call Kotlin extension functions from Java, sure, but you can't call them with extension function syntax, you must call them like static methods. If you, for example, define
// file: Foo.kt
fun Bar.baz() { ... }
then in Java, you would call this as
FooKt.baz(bar);
I don't think you want to have toReadUhfTagInfo as a member function on the ReadUhfTagInfo class. That would imply that, in order to convert a UHFTAGInfo to a ReadUhfTagInfo, you already need a ReadUhfTagInfo object (which will presumably go unused except to serve as the receiver object.
Extension functions defined inside a class are member extensions and essentially have two receivers.
You can declare extensions for one class inside another class. Inside such an extension, there are multiple implicit receivers - objects whose members can be accessed without a qualifier. An instance of a class in which the extension is declared is called a dispatch receiver, and an instance of the receiver type of the extension method is called an extension receiver.
If you want the extension method to act like a static method in Java (i.e. not require an instance of the enclosing class to execute), then you do the same thing we do with all static methods in Kotlin: We put it in a companion object.
class ReadUhfTagInfo(var epc: String, var cnt: Int, var rssi: Int?)
{
companion object {
fun UHFTAGInfo.toReadUhfTagInfo(): ReadUhfTagInfo {
return ReadUhfTagInfo(this.epc, this.count, this.rssi.toIntOrNull())
}
}
}
As pointed out in the comments, this will still require the name to be imported into the current scope (as all extension methods do), but it won't require a receiver of type ReadUhfTagInfo to call anymore.

Kotlin: referring to delegate that is not passed by constructor

I want to use Kotlin delegation in a particular context.
The delegate should not be passed in the constructor.
I want to keep a reference to the delegate for later use in the code. From within the method that I override, say printMessage(), I still need to call the delegate the same way you'd call super.printMessage() in polymorphic inheritance.
I can do the first by simply instantiating an anonymous delegate in the by clause (class Derived() : Base by BaseImpl(42) using Kotlin's documentation example). However,
this prevents me from accessing the anonymous delegate, as there is no way that I know to reference it.
I want to do something similar to the following. The following however doesn't compile with error 'this' is not defined in this context.
class Derived() : Base by this.b {
val b: Base = BaseImpl(42)
override fun printMessage() {
b.printMessage()
print("abc")
}
}
I do need a separate delegate for each instance of my Derived class. So moving b as a global variable is not an option for me.
The closest I got to what I need is with an optional parameter to the constructor. This is not a good option neither, as I don't want to allow the construction of my Derived class with arbitrary delegates.
You can do this using a private primary constructor and a public secondary constructor:
class Derived private constructor(val b: Base) : Base by b {
constructor(): this(BaseImpl(42))
override fun printMessage() {
b.printMessage()
print("abc")
}
}
If you don't need a reference to the delegate, you can also say simply,
class Derived : Base by BaseImpl(42)

Check instance of anonymous object

If I create an anonymous class in Kotlin like this:
if(condition) {
object: Foo() {
fun bar() {
// code
}
}
} else {
Foo()
}
Is there a way to check in the code that the current instance has is the object class and hence I can call bar() which does not exist in Foo?
That object expression is creating an anonymous class, like m.antkowicz has pointed out:
Note that anonymous objects can be used as types only in local and private declarations. If you use an anonymous object as a return type of a public function or the type of a public property, the actual type of that function or property will be the declared supertype of the anonymous object, or Any if you didn't declare any supertype. Members added in the anonymous object will not be accessible.
That means your if expression is returning a local type which is known to contain bar(), but once it leaves that scope it will be declared as the supertype you used - it will be a Foo which does not contain a bar() method.
So, you need to use a supertype that does contain that member - you can use an interface to this, just like when you define a (non-anonymous) class:
interface Bar {
fun bar()
}
object : Foo(), Bar {
override fun bar() {...}
}
then you can use is Foo and is Bar to check which types the object has.
If you want to arbitrarily add functions to objects outside of the type system, and have other code able to know those functions are there, you're probably looking at doing reflection

Why/How does this extension function work? How to call it without `with`?

While taking the "Kotlin for Java Developers" Coursera course, I came across this construction, where an extension function for a contained instance seems to have access to the containing class' private fields. Note how the Data class is implemented outside of Container and does not have access to Container's fields, but the Data.printMe() extension function can access Container's private containerVal member:
data class Data (val data: String)
class Container (private val containerVal: String, val data: Data){
fun Data.printMe() {
println("data: $data - in container: ${this#Container.containerVal}")
}
}
fun main() {
val c = Container("mycontainer", Data("mydata"))
// Can I call Data.printMe without using `with`?
// val d = c.data.printMe();
with (c) {
// Prints: data: mydata - in container: mycontainer
data.printMe();
}
}
Pretty cool that Data.printMe can access Container's private members. The with(c) is apparently what allows that. I can see lots of use cases for this, just like how in the course example extension functions for a game's Cells can access the containing Board without the Cell class itself being polluted by and tightly coupled with Board.
Does this "approach" have a name? And is there a syntax to call c.data.printMe "directly" without using with? The with documentation doesn't mention this use case.
The printMe() method has two receivers: the dispatch receiver and the extension receiver. The dispatch receiver is the instance of the class in which the extension is declared, and the extension receiver is the instance of the receiver type of the extension method. You are accessing contaiverVal in the context of a Container instance (dispatch receiver), not a Data instance (extension receiver).
If you try to do the opposite and access a private property of the Data class inside the printMe(), you will get a compiler error.
when you define an extension function as a member of a class, it is only usable in the context that class. You can access it inside the class or using a scope function where the context object is available as a lambda receiver (this). Those functions are run, with and apply.

Why do I need a parameter in a primary constructor without val/var modifier in Kotlin?

If I create a class, I can pass a parameter:
class Person(name: String) {
}
I also can write the same, but with val and then I'll be able to use properties to get this value, when I created an object.
val person = Person("Name")
person.name
The question is: why do I need just a parameter without the val? Where, how and why should I use it?
If you use varor val in the constructor, you are declaring properties and initializing them directly. If you don't, those parameters are used for initialization purposes:
class Customer(name: String) {
val customerKey = name.toUpperCase()
}
https://kotlinlang.org/docs/reference/classes.html
It's used when you don't want constructor arguments to become named properties on the class.
If you use val, you get a read-only property. If you use var, you get a mutable property. Otherwise, you get nothing [auto-defined].