Kotlin - How i can access my new class extension function from another file - kotlin

I am very new to Kotlin.
I want to be able to add a function to my abstract class, so when I define that function I will be able to invoke that on every child from that class(they inherit the abstract class)
However,I want to define those extension functions in other file.
I can't access those functions when i try to invoke them on a particular child implementation of the abstract class.
What are the rules, that I need to made to resolve my problem?
I want to by able achieve something like this:
abstract class Parent(val val1, val val2, val val3){}
class Child(var val1, var val2, var val3) : Parent(val1, val2, val3){}
class Child2(var val1, var val2, var val3) : Parent(val1, val2, val3){}
The extension method for parent and all childs:
fun Parent.convertToChild2( ): Child2? {
return //some creation method of Child2
}
And I want to be able to invoke this:
child: Child
child.convertToChild2
I defined all classes in separate file and also the extension function in other file.
I cannot access the function like this - is not visible.

The answer for my question, that satisfies me is just to extract the method to some "object" structure in other file and whenever we want to access that function we must import the path(package.object.method) to this.
But the problem is, that IDE is not propose me the path to my extension function - i must import it by myself.
I am using Android Studio 3 preview, hope this will be fixed.
UPDATE
It is better to define those function in just plain Kotlin file, so the functions will be not owned by any structure. Then it will be not a problem with importing those automatically by IDE from any place.

I believe that there is a misunderstanding here about extension functions. Extension functions are regular static functions that take in an instance of the receiver class as a parameter implicitly when you define the function and operate on it.
These static functions (aka extension functions) have some limitations.
They are not added to the class hierarchy so subclasses can not inherit them (if you define extension function for parent class you can't expect that method to be present in child class)
They don't have access to the private properties of the class that they are extending.
Also, they are resolved statically, for example (taken from here)
open class Shape
class Rectangle: Shape()
fun Shape.getName() = "Shape"
fun Rectangle.getName() = "Rectangle"
fun printClassName(s: Shape) {
println(s.getName())
}
printClassName(Rectangle())
This example prints "Shape", because the extension function being called depends only on the declared type of the parameter s, which is the Shape class.

First of all: There a many errors in your source code, you should fix before asking the question here (missing type annotations in constructors, missing val/var etc.).
To your question:
Normally, you can access extension functions even if defined in different kt files. Read the official docs covering extension scopes.
It's important to import your extension function

There is a way to do that:
fun <T: Parent> T.toChild2() {
TODO()
}
Child(...).toChild2()

Related

Load kotlin resource from outside a class

I have a couple of top level functions in my Kotlin code:
fun getSomeText(path: String): String? {
// return contents of the path relative to src/main/resources/some_dir
}
Where this function simply returns the content of the file in src/main/resources/some_dir/path. I don't have a class to access ::class.java.getResource from. I've seen people using {}::class.java.getResource, but this creates a new object whenever a resource is accessed. Is there a built-in way to access a resource from a static context in kotlin?
If you do not want to create an anomymous class, and (as I understand from your comment) the given path should always be relative to a given path "/my_custom_dir", you can for instance use Any's class's class to get the resource from that class:
fun getSomeText(path: String): String? =
Any::class::class.java.getResource("/my_custom_dir/$path").readText()
As far as I can tell, it does not work with just Any::class, but with Any::class::class.
Further, please note that the leading slash in the path makes sure that you do look for a path relative to your classpath's root and not relative to the given class's location.
If you can be sure that the function is called from inside a class, an alternative would be to use the class of the caller like this:
fun <T : Any> T.getSomeText(path: String): String? =
this::class.java.getResource("/my_custom_dir/$path").readText()
From inside any class this function can just be called like getSomeText(...) without the need to explicitly specify the receiver. When you take away the /my_custom_dir/ part of the path, this function has the advantage that you can also use it to load some resource relative to the calling class.

Kotlin - Return Type For Generic Inheritance

I have a generic parent class:
open class Parent<T>{/*...*/}
and I have some derived classes that implement a specific instance of the generic parent:
class Derived1 : Parent<Foo1> {/*...*/}
class Derived2 : Parent<Foo2> {/*...*/}
where Foo1 and Foo2 are some classes defined elsewhere
I now need to create a function that returns a different derived class based on some input parameter:
fun getDerived(derived: SomeEnumType): Parent{
//return the correct derived class
}
Of course the line above won't compile because Parent requires a generic parameter. The Derived classes are not of the same type, so I wouldn't expect to be able to handle this polymorphically. How can I achieve this? I am familiar with kotlin.Any but this seems like cheating.
If it helps, I am using this pattern to parse json in the correct child class with the gson library (by overriding the deserializer)
You could get away with Parent<*> but if there is a relationship between Foo1 and Foo2 (e.g extending a common interface, Buzz) then you could use something like Parent<out Buzz>.
IIRC, <*> is like Java's wildcard <?>. Not bounding the response type will mean you'll need some type guards at the call site of your function getDerived to make the response inspectable.

Function reference for class constructor nested within generic parent class

If I have
sealed class Foo<A> {
data class Bar<A>(val value: Int): Foo<A>()
}
and I want to refer to the Bar<Int> constructor as an implicit lambda using the :: operator, then none of the following are accepted as valid syntax:
Foo<Int>::Bar<Int>
::Foo.Bar<Int>
::(Foo.Bar<Int>) (the compiler tells me that this syntax is reserved for future use).
I can refer to it if I explicitly import the nested class constructor into the scope using
import com.package.Foo.Bar
which allows me to write ::Bar for the constructor and Bar<Int>::value for the property getter. But I have to do this for every nested constructor, and it kind of defeats the advantage of using the :: operator to save typing.
Is there a notation that I have missed which allows me to avoid having to import all nested class names and constructors?
Edit
My original example did not involve generics, which turns out was an oversimplification of the problem I had in my actual code that I am working on, which does use generics.
It turns out that for nested classes without generic parameters, the Foo::Bar notation actually works, so my original question had a false premise. It is, however, not possible to create callable references to constructors within generic classes. This is documented in the following bug report: https://youtrack.jetbrains.com/issue/KT-15952
It is a known bug in the language design: https://youtrack.jetbrains.com/issue/KT-15952
This bug report did however lead me to another workaround using type aliases which is equivalent to adding aliased imports, but has the advantage that you can put the alias where you want, and even share it between modules. In summary, this is the two only viable solutions I know of so far:
// Method one: Import Foo.Bar
import Foo.Bar as BarImported
sealed class Foo<A> {
data class Bar<A>(val value: A): Foo<A>()
}
val ctor: (Int) -> Foo<Int> = ::BarImported
val getter: (BarImported<Int>) -> Int = BarImported<Int>::value
// Method two: Alias Foo.Bar
typealias BarAlias<A> = Foo.Bar<A>
val ctor2: (Int) -> Foo<Int> = ::BarAlias
val getter2: (Foo.Bar<Int>) -> Int = BarAlias<Int>::value
What about wild card imports?
import com.package.Foo.*

Utils class in Kotlin

In Java, we can create an utilities class like this:
final class Utils {
public static boolean foo() {
return false;
}
}
But how to do this in Kotlin?
I try using functions inside object:
object Utils {
fun foo(): Boolean {
return false
}
}
But when call this method from Java code it need to add INSTANCE. Ex: Utils.INSTANCE.foo().
Then I change to declare it as top-level function (without class or object):
#file:JvmName("Utils")
#file:JvmMultifileClass
fun foo(): Boolean {
return true
}
Then I can call Utils.foo() from Java code. But from Kotlin code I got Unresolved reference compiler error. It only allow be to use foo() function directly (without Utils prefix).
So what is the best approach for declaring utils class in Kotlin?
The last solution you've proposed is actually quite idiomatic in Kotlin - there's no need to scope your function inside anything, top level functions are just fine to use for utilities, in fact, that's what most of the standard library consists of.
You've used the #JvmName annotation the right way too, that's exactly how you're supposed to make these top level functions easily callable for Java users.
Note that you only need #JvmMultifileClass if you are putting your top level functions in different files but still want them to end up grouped in the same class file (again, only for Java users). If you only have one file, or you're giving different names per file, you don't need this annotation.
If for some reason you want the same Utils.foo() syntax in both Java and Kotlin, the solution with an object and then #JvmStatic per method is the way to do that, as already shown by #marianosimone in this answer.
You'd need to use #JvmStatic for that:
In Kotlin:
object Utils {
#JvmStatic
fun foo(): Boolean = true
}
val test = Utils.foo()
In Java:
final boolean test = Utils.foo()
Note that the util class you used in Java was the only way to supply additional functions there, for anything that did not belong to a particular type or object. Using object for that in Kotlin does not make any sense. It isn't a singleton, right?
The second approach you mentioned is rather the way to go for utility functions. Internally such functions get translated to static ones and as you can see they become the static util classes in Java you are searching for, as you can't have standalone functions in Java without a class or enum. In Kotlin itself however they are just functions.
Some even count utility classes to the anti-patterns. Functions on the other hand make totally sense without a class or object whose name hasn't so much meaning anyway.

When should one prefer Kotlin extension functions?

In Kotlin, a function with at least one argument can be defined either as a regular non-member function or as an extension function with one argument being a receiver.
As to the scoping, there seems to be no difference: both can be declared inside or outside classes and other functions, and both can or cannot have visibility modifiers equally.
Language reference seems not to recommend using regular functions or extension functions for different situations.
So, my question is: when do extension functions give advantage over regular non-member ones? And when regular ones over extensions?
foo.bar(baz, baq) vs bar(foo, baz, baq).
Is it just a hint of a function semantics (receiver is definitely in focus) or are there cases when using extensions functions makes code much cleaner or opens up opportunities?
Extension functions are useful in a few cases, and mandatory in others:
Idiomatic Cases:
When you want to enhance, extend or change an existing API. An extension function is the idiomatic way to change a class by adding new functionality. You can add extension functions and extension properties. See an example in the Jackson-Kotlin Module for adding methods to the ObjectMapper class simplifying the handling of TypeReference and generics.
Adding null safety to new or existing methods that cannot be called on a null. For example the extension function for String of String?.isNullOrBlank() allows you to use that function even on a null String without having to do your own null check first. The function itself does the check before calling internal functions. See documentation for extensions with Nullable Receiver
Mandatory Cases:
When you want an inline default function for an interface, you must use an extension function to add it to the interface because you cannot do so within the interface declaration (inlined functions must be final which is not currently allowed within an interface). This is useful when you need inline reified functions, for example this code from Injekt
When you want to add for (item in collection) { ... } support to a class that does not currently support that usage. You can add an iterator() extension method that follows the rules described in the for loops documentation -- even the returned iterator-like object can use extensions to satisfy the rules of providing next() and hasNext().
Adding operators to existing classes such as + and * (specialization of #1 but you can't do this in any other way, so is mandatory). See documentation for operator overloading
Optional Cases:
You want to control the scoping of when something is visible to a caller, so you extend the class only in the context in which you will allow the call to be visible. This is optional because you could just allow the extensions to be seen always. see answer in other SO question for scoping extension functions
You have an interface that you want to simplify the required implementation, while still allowing more easy helper functions for the user. You can optionally add default methods for the interface to help, or use extension functions to add the non-expected-to-be-implemented parts of the interface. One allows overriding of the defaults, the other does not (except for precedence of extensions vs. members).
When you want to relate functions to a category of functionality; extension functions use their receiver class as a place from which to find them. Their name space becomes the class (or classes) from which they can be triggered. Whereas top-level functions will be harder to find, and will fill up the global name space in IDE code completion dialogs. You can also fix existing library name space issues. For example, in Java 7 you have the Path class and it is difficult to find the Files.exist(path) method because it is name spaced oddly. The function could be placed directly on Path.exists() instead. (#kirill)
Precedence Rules:
When extending existing classes, keep the precedence rules in mind. They are described in KT-10806 as:
For each implicit receiver on current context we try members, then local extension functions(also parameters which have extension function type), then non-local extensions.
Extension functions play really well with the safe call operator ?.. If you expect that the argument of the function will sometimes be null, instead of early returning, make it the receiver of an extension function.
Ordinary function:
fun nullableSubstring(s: String?, from: Int, to: Int): String? {
if (s == null) {
return null
}
return s.substring(from, to)
}
Extension function:
fun String.extensionSubstring(from: Int, to: Int) = substring(from, to)
Call site:
fun main(args: Array<String>) {
val s: String? = null
val maybeSubstring = nullableSubstring(s, 0, 1)
val alsoMaybeSubstring = s?.extensionSubstring(0, 1)
As you can see, both do the same thing, however the extension function is shorter and on the call site, it's immediately clear that the result will be nullable.
There is at least one case where extension functions are a must - call chaining, also known as "fluent style":
foo.doX().doY().doZ()
Suppose you want to extend the Stream interface from Java 8 with you own operations. Of course, you can use ordinary functions for that, but it will look ugly as hell:
doZ(doY(doX(someStream())))
Clearly, you want to use extension functions for that.
Also, you cannot make ordinary functions infix, but you can do it with extension functions:
infix fun <A, B, C> ((A) -> B).`|`(f: (B) -> C): (A) -> C = { a -> f(this(a)) }
#Test
fun pipe() {
val mul2 = { x: Int -> x * 2 }
val add1 = { x: Int -> x + 1 }
assertEquals("7", (mul2 `|` add1 `|` Any::toString)(3))
}
There are cases where you have to use extension methods. E.g. if you have some list implementation MyList<T>, you can write an extension method like
fun Int MyList<Int>.sum() { ... }
It is impossible to write this as a "normal" method.