Use extension function from different context in Kotlin - kotlin

Here is an example of what I'd like to achieve:
open class A {
open fun Int.foo() {
print("foo")
}
}
object B: A() {
val number = 5;
override fun Int.foo() {
print("overriden foo");
// I want to call the A.(Int.foo())
}
}
B.number.foo(); //outputs: "foooverriden foo"
First of all, does anything like this exist? Can I somehow assume number to be in the context of class A in its override method? How would I write this?
The more I think about it the more it twists my mind. Of course, you cannot call number.super.foo() because super for number is kotlin.Number. You cannot cast it to A because Int has nothing to do with A. The only way I can think about solving this to somehow import the extension function itself and rename it with as, but I cannot do that here since it is inside a class, so I cannot just import it. Any suggestions?
My use case for this is that I have a class where I manipulate some data, then in special cases, I want to manipulate it differently, but fall back to the original code as the last option. I could use normal functions instead of extension functions of course, but in my case, it comes natural to use extension functions, so I wanted to see if this could be achieved somehow.

It looks like this is impossible so far, I'm afraid.
There's an open issue for this on JetBrains' issue-tracking system: KT-11488.  There's a Kotlin work-around there, though that needs tweaks to the class designs.
(Also discussed on the JetBrains discussion board.  That mentions another workaround requiring a Java class.)

override fun Int.foo() {
print("overriden foo")
with (A()) {
foo()
}
}
Of course this is a bit of a hack and will get worse if A has some state which foo() depends on, which you'll then need to set manually.

Related

Get Kotlin class from string a call a method in it

I have 2 simple classes in kotlin
package com.sample.repo
class SampleClassA() {
fun test(): String {
return "Do things A way"
}
}
package com.sample.repo
class SampleClassB() {
fun test(): String {
return "Do things B way"
}
}
Now i have a configuration file that tells me which class to use.
Let's say i have a string
val className = "SampleClassA" // assuming all classes are in same package
I want obtain this class and invoke the test function in it
I was able to do below
fun `some random test`() {
val className = "SampleClassA"
val packageName = "com.sample.repo"
val kClass = Class.forName("$packageName.$className").kotlin
val method = kClass.members.find { it.name == "test" }
// How do i call this method ??
}
}
You should create an object of the class and then call method on it.
Example:
//...code from your example
val method = kClass.members.find { it.name == "test" }!!
val obj = kClass.primaryConstructor?.call()
val result = method.call(obj)
println(result)
I wouldn't do it that way. Instead, I'd require that the classes you're choosing between implement some common interface, which you can then refer to directly. For example:
interface Testable {
fun test(): String
}
 
package com.sample.repo
class SampleClassA() : Testable {
override fun test() = "Do things A way"
}
 
package com.sample.repo
class SampleClassB() : Testable {
override fun test() = "Do things B way"
}
 
fun `some random test`() {
val className = "SampleClassA"
val packageName = "com.sample.repo"
val testable = Class.forName("$packageName.$className").kotlin
.createInstance() as Testable
testable.test()
}
I don't know if this applies to OP, but judging from some of the questions asked here on StackOverflow, many people are coming to Kotlin from weakly-typed languages where it's common to use ‘string typing’ to fudge the lines between types, to assume that developers can always be trusted, and that it's fine to discover problems only at runtime. Of course, it's only natural to try to apply the patterns and techniques you're familiar with when learning a new language.
But while that style of programming is possible in Kotlin (using reflection), it's rarely a good fit. If you'll excuse one of my standard rants, reflection is slow, ugly, fragile, insecure, and hard to maintain; it's easy to get wrong, and forces you to handle most errors at runtime. Don't get me wrong: reflection is a very valuable tool, and there are situations where it's vital, such as writing frameworks, plug-ins, some forms of dependency injection, build tools, and similar. But reflection should be a tool of last resort — for general application coding, there's almost always a better approach, usually one that's more concise, easier to read, performs better, spots more problems at compile-time, can be autocompleted in your IDE, and works with the language and its type system, not against it.
Kotlin is a strongly-typed language; it has a fairly sophisticated type system (and type inference, so you don't need to keep repeating yourself), which is safer and smarter, turns many errors into compile-time errors, allows many optimisations, and is effectively self-documenting (making more explicit the contract between called code and its callers). It's better to try to work with the type system when you can, rather than subvert if (which is what reflection does).
The example above uses reflection to create an instance of a class which is assumed to implement the Testable interface (and will give ugly errors at runtime if the class isn't available, doesn't implement that interface, or doesn't have a public constructor with no required params), but after that uses normal, typed code which is much safer.
(In fact, depending how your test code is structured, you might find a way to configure it with Testable instances rather than String classnames, and avoid reflection altogether. That would be simpler and safer still.)

T except one class

Suppose I've a class called Devil
class Devil
and I've method called support
fun <T> support(t : T){
}
I want to restrict this function to only accept classes other than Devil (all classes in the world, but not Devil). Something like
fun <T except Devil> support(t : T){
}
How do I do this in Kotlin? Is this even possible?
This is very likely an XY problem, so please do not apply this solution without considering something else.
One way to achieve this is to declare a non-generic overload of support() with the explicit type Devil, and deprecate that function with ERROR level:
fun <T> support(t: T) {
// do your stuff
}
#Deprecated("support() cannot be used with type Devil", level = DeprecationLevel.ERROR)
fun support(devil: Devil) {
error("NOPE.")
}
Note that this would also exclude subtypes of Devil - which is not explicitly stated in your question, but might be what you want.
However, nothing prevents users from working around it by explicitly calling the generic overload by specifying a type in <...>:
support<Devil>(Devil()) // compiles fine
support<Any>(Devil()) // compiles fine
Similarly, as #gidds pointed out, this approach also doesn't prevent compilation if you pass in a variable with a static type that is not Devil even if it holds an instance of Devil (because the compiler will choose the generic overload in that case):
val hiddenDevil: Any = Devil()
support(hiddenDevil) // compiles fine

kotlin get static type of a class property

I'm trying to get the type of some class properties in order to strongly typing my Kotlin Code.
In typescript, we can do this (stupid examplebut this is to explain)
class Test {
private _prop:string
constructor(val:Test["_prop"]){
this._prop = val
}
public get prop():Test["_prop"] { return this._prop}
}
const t:Test["_prop"] = "fdds"
The benefit here is that if I need to chnange the type of "_prop", no need to refactor the whole code, as the type is find thanks to Test["_prop"].
Is there a way to do this in Kotlin ?
I've seen reflection functions in Kotlin, but can't get what I want
Kotlin code :
class Test(val prop:Int) {
fun ppr() {
println(prop)
}
fun getProp():Int {
return prop
}
}
fun main() {
println("Hello, world!!!")
var t:Test = Test(4)
t.ppr()
var a:Int = t.getProp() // how to change :Int by "return type of func Test.prop
}
What you're trying to do is the opposite of strong typing. The point of a strong-typed system is that you're defining exactly what things are, and the system requires you to interact with those things correctly, and prevents you from doing things those types don't support
You're working with specific types and defined type hierarchies, and the way you can interact them is strongly enforced. It's possible to go outside the type system, e.g. with unchecked casts, or by reflection (which can get close to throwing the whole thing out completely) - but that's losing the benefits of strong typing, the guarantees and assistance it can provide, and makes errors a lot more likely
Basically if you want to change the type, you're supposed to refactor it. That lets the system handle it all for you systematically, and it will point out any problems that change might introduce, so you can resolve and handle them. This is another benefit of a strongly typed system - it can help you in this way
If you want to stay within the type system, but just want to update a type and avoid creating changes in a bunch of files, then #Sweeper's typealias approach will work - kinda abstracting a type definition away to one place (and you can give it a more meaningful name that doesn't reflect the specific type it happens to be right now). But if you meaningfully change what that underlying type is, your code will probably have to handle it anyway, unless you're just doing a common call on it like toString().
I might have got what you're asking for wrong, but I wanted to point this stuff out just in case, since you were talking about reflection and all!
You can't do it exactly like that in Kotlin, but you can declare a type alias, which sort of achieves the same result - enabling you to change the type of multiple things by editing only one place.
typealias PropType = Int
class Test(val prop: PropType) {
fun prop(): PropType {
return prop
}
}
To change the type of both, just change the typealias PropType = Int line.
However, note that you don't actually need to do this if you just want to write a getter. You don't need to explicitly write getters if all it does is just returning the property's value. If you want to do something extra in the getter, you can do:
class Test(prop: Int) {
val prop = prop
get() {
// do something extra in the getter
println("getting prop!")
return field // return the underlying field
}
}
The getter will be called whenever you access Test.prop, and again, you only need to change one place to change the type of the property.

KClass::memberExtensionFunctions always be empty

Code
import kotlin.reflect.full.*
class FooBar(val bar: String)
fun FooBar.baz(): Unit {println(this.bar)}
fun main(args: Array<String>) {
FooBar::class.declaredMemberExtensionFunctions.forEach {
println(it)
}
FooBar::class.memberExtensionFunctions.forEach {
println(it)
}
}
Output is empty
This is because declaredMemberExtensionFunctions only returns extension functions that are declared inside a class (as seen in the docs) and FooBar.baz() is a top level declaration (So it is not declared inside FooBar.
class FooBar(val bar: String) {
fun FooBar.baz(): Unit {
println(this.bar)
}
}
While I imagine this is not what you want, structuring the extension function like this would make your main method output lines.
TLDR: You aren't going to be able to do this. Because extension functions can be declared everywhere, you are limited in what the reflection system can do for you.
There is a thread on kotlinlang.org that covers this exact question and why it is not possible.
Essentially, Kotlin's declaredMemberExtensionFunctions function is able to list extension functions which are declared as part of the class, not externally. The docs state:
Returns extension functions declared in this class.
And of course, memberExtensionFunctions behaves similarly:
Returns extension functions declared in this class and all of its superclasses.
Here's what #Yole says in that thread as to why this is not possible:
The task of finding all extension functions for Foo is equivalent to finding all methods which have Foo as the first parameter. Neither of these is possible without accessing every single class in your application through reflection.
#Yole is on here, he might be able to provide a more authoritative answer for you.

Should we avoid naming a function same as an existing class in Kotlin? Why?

Kotlin allows to name a function same as an existing class, e.g. HashSet with initializer function could be implemented like this:
fun <T> HashSet(n : Int, fn: (Int) -> T) = HashSet<T>(n).apply {
repeat(n) {
add(fn(it))
}
}
When used, it looks like a normal HashSet constructor:
var real = HashSet<String>()
var fake = HashSet(5) { "Element $it" }
Should this be avoided or encouraged and why?
UPD
In the updated coding conventions, there's a section on this topic:
Factory functions
If you declare a factory function for a class, avoid giving it the same name as the class itself. Prefer using a distinct name making it clear why the behavior of the factory function is special. Only if there is really no special semantics, you can use the same name as the class.
Example:
class Point(val x: Double, val y: Double) {
companion object {
fun fromPolar(angle: Double, radius: Double) = Point(...)
}
}
The motivation I described below, though, seems to still hold.
As said in documentation about the naming style:
If in doubt default to the Java Coding Conventions such as:
methods and properties start with lower case
One strong reason to avoid naming a function same to a class is that it might confuse a developer who will use it later, because, contrary to their expectations:
the function won't be available for super constructor call (if the class is open)
it won't be visible as a constructor through reflection
it won't be usable as a constructor in Java code (new HashSet(n, it -> "Element " + it) is an error)
if you want to change the implementation later and return some subclass instance instead, it will get even more confusing that HashSet(n) { "Element $it" } will construct not a HashSet but, for example, a LinkedHashSet
It's better to show it explicitly that it's a factory function, not a constructor, to avoid this confusion.
Naming a function same to a class is generally avoided in stdlib, too. Given SomeClass, in stdlib a preferred naming style for factory functions is someClassOf, someClassBy or whatever explains the semantics of the function best. The examples:
generateSequence { ... } and sequenceOf(...)
lazy { ... } and lazyOf(...)
compareBy { ... }
listOf(...), setOf(...), mapOf(...)
So, one should definitely have strong reason to have a function mimic a constructor.
Instead, a function's name might tell a user more (even everything) about its usage.
I agree with +hotkey. It's probably best to avoid confusion in this case.
If it's only used internally and all the other devs (if any) are okay with it, though, I'd say to go for it. Python acknowledges that idea and I love it. Heck, they go both ways, being okay with you naming a class in function case, too, if it feels more like it's acting like a function. But, Python doesn't have to deal with Java interop, so definitely don't do it for public code.