Please help me to understand this Binary Tree Node class!

I’m making a binary tree with the help of a blog, first I’m making a node class but what’s happening inside there is mysterious to me…
data class TreeNode(var leftTreeNode: TreeNode? = null,
var rightTreeNode: TreeNode? = null,
val nodeData: T){

fun link(leftTreeNode: TreeNode<T>?, rightTreeNode: TreeNode<T>?)=this.apply{
linkLeft(leftTreeNode!!).linkRight(rightTreeNode!!)
}

private fun linkLeft(left: TreeNode<T>) = this.apply { leftTreeNode = left }

private fun linkRight(right: TreeNode<T>) = this.apply { rightTreeNode = right }

fun depth(value: Int) = this.apply { depth = value }

}

first, can we link two objects using a dot linkLeft(leftTreeNode!!).linkRight(rightTreeNode!!)

exactly what this dot( . ) is doing here
And then this depth function why it is assigning value to the

depth I know about depth is the number of edges from the root to a specific node.

Thanks in advance

I’m guessing the code you posted is from the blog?⠀(I hope that by ‘making’ you mean more than just ‘copy-and-pasting’…)

Also, your code would be easier to follow if it was formatted properly.⠀ (Right now only some of the lines are being treated as code, and I think there must be a <T> that’s not showing.)

Anyway.⠀The relevant factor is that all four methods return this, i.e. the TreeNode instance they were called on.⠀That’s usually so that you can chain calls to them, so instead of e.g.:

val myNode = TreeNode(/*…*/)
myNode.linkLeft(/*…*/)
myNode.linkRight(/*…*/)
myNode.depth(/*…*/)
return myNode

You can simply:

return TreeNode(/*…*/)
       .linkLeft(/*…*/)
       .linkRight(/*…*/)
       .depth(/*…*/)

in one expression, without needing a temporary variable.⠀(That’s what the . you asked about is doing.)

This is called a ‘fluent interface’, and is moderately common in Java.⠀But it’s much less common in Kotlin, because Kotlin has better ways to achieve the same end, that work for all methods.⠀ For example:

return TreeNode(/*…*/).apply {
    linkLeft(/*…*/)
    linkRight(/*…*/)
    depth(/*…*/)
}

(That’s how those four methods themselves are implemented!)

So in Kotlin, you wouldn’t normally bother to have those methods return anything at all, which would make them simpler.⠀— But in that case, you don’t even need to have them at all!⠀Because those properties are declared as vars, Kotlin automatically creates getters and setters for them.⠀So all you really need is:

data class TreeNode<T>(var leftTreeNode: TreeNode? = null,
                       var rightTreeNode: TreeNode? = null,
                       val nodeData: T)

(The blog you got this from may have been translated from Java, or may be written by someone still using Java idioms.)