Add protected and internal visibility to function in kotlin - kotlin

I have an open (or abstract) public class that contains an open (or abstract) fun (or var or val) that I do not want to expose as public.
Unfortunately I also need to call that fun from inside my current package.
If I mark it as internal that class cannot be inherited correctly from another package(ide gives warning: inherits invisible abstract members), if I mark it as protected the fun cannot be access from inside the current package
Any way to bypass this?

A dirty way is to add a proxy internal method and call that method inside your package:
abstract class AbstractClass {
protected abstract fun isTrue(int: Int): Boolean
internal fun isTrueInternalProxy(int: Int): Boolean {
return isTrue(int)
}
}

Related

How does class know which implementation of an interface to take?

I have a class with a function like so:
#Component
class UpdateService(
private val storeGateway: UpdateStoreGateway,
private val loadGateway: UpdateLoadGateway,
private val updateNotify: UpdateNotify,
) : UpdateStorage {
override fun delete(key: UpdateKey) {
if (loadGateway.loadByKey(key) != null)
storeGateway.delete(key)
updateNotify.deleted()
}
}
}
UpdateStoreGateway, UpdateLoadGateway and UpdateNotify are Interfaces. Since I'm new to Kotlin I can't quite grasp how the method override fun delete(key: UpdateKey) knows which implementation of the methods to take since there is no mention of the implementation class.
It's implementing all three!
An interface requires that all implementing clases must provide method(s) with the required signature(s). (That is: having the required name, and taking the required parameter type(s).) But there are no restrictions on where that method is defined: it could be in the implementing class, or inherited from a superclass. And similarly, there are no restrictions on a method implementing more than one interface, if the signature matches.
All that matters is that users of the class know they can call the method(s) specified in all implemented interfaces; they shouldn't know or care about the details.

Make a function execute only in Kotlin interfaces?

If I have an interface, is there any easy way I can declare a function to make it a public member, but non-overridable? Meaning, it would be exclusively callable and could not be set or overridden by its descendants
interface IFoo {
fun ExecuteOnly(){
// Do Something
}
}
I read a book recently by CommonsWare where this situation was described.
and I quote it from there:
"... As a result, anything in an interface hierarchy is permanently open , until you start
implementing the interfaces in classes. If that is a problem — if you have some
function that you really want to mark as final — use abstract classes, not interfaces..."
You can define an extension function on the interface.
fun IFoo.executeOnly() {
}
It will still be possible for someone to define a member function with that name in a class implementing IFoo but the intention is quite clear. And anyway when using an object via a IFoo reference the IFoo extension will be chosen.
No, you cannot. That's not how Kotlin's interface is implemented.
You can use an abstract class instead
abstract class Foo {
fun executeOnly(){
// Do Something
}
}
Ofcourse You Can... Actually there is not much difference bw kotlin interfaces and abstract classes... simply add a body and a private modifier..
interface MyInterface {
fun triggerTakeMe(){
takeMe()
}
private fun takeMe(){
println("Taken")
}
}
class MyClass : MyInterface
fun main() {
val obj = MyClass()
obj.triggerTakeMe()
}

Instantiating classes from non-reified type parameters

I'm building an ORM for use with jasync-sql in Kotlin and there's a fundamental problem that I can't solve. I think it boils down to:
How can one instantiate an instance of a class of type T, given a
non-reified type parameter T?
The well known Spring Data project manages this and you can see it in their CrudRepository<T, ID> interface that is parameterised with a type parameter T and exposes methods that return instances of type T. I've had a look through the source without much success but somewhere it must be able to instantiate a class of type T at runtime, despite the fact that T is being erased.
When I look at my own AbstractRepository<T> abstract class, I can't work out how to get a reference to the constructor of T as it requires accessing T::class.constructors which understandably fails unless T is a reified type. Given that one can only used reified types in the parameters of inline functions, I'm a bit lost as to how this can work?
On the JVM, runtime types of objects are erased, but generic types on classes aren't. So if you're working with concrete specializations, you can use reflection to retrieve the type parameter:
import java.lang.reflect.*
​
abstract class AbstractRepository<T>
​
#Suppress("UNCHECKED_CAST")
fun <T> Class<out AbstractRepository<T>>.repositoryType(): Class<T> =
generateSequence<Type>(this) {
(it as? Class<*> ?: (it as? ParameterizedType)?.rawType as? Class<*>)
?.genericSuperclass
}
.filterIsInstance<ParameterizedType>()
.first { it.rawType == AbstractRepository::class.java }
.actualTypeArguments
.single() as Class<T>
​
class IntRepository : AbstractRepository<Int>()
class StringRepository : AbstractRepository<String>()
interface Foo
class FooRepository : AbstractRepository<Foo>()
class Bar
class BarRepository : AbstractRepository<Bar>()
​
fun main() {
println(IntRepository::class.java.repositoryType())
println(StringRepository::class.java.repositoryType())
println(FooRepository::class.java.repositoryType())
println(BarRepository::class.java.repositoryType())
}
class java.lang.Integer
class java.lang.String
interface Foo
class Bar
In your own CrudRepository you can add a companion object with an inline fun which is responsible to instantiate your repository by passing to it the corresponding class.
class MyCrudRepository<T> protected constructor(
private val type: Class<T>,
) {
companion object {
inline fun <reified T : Any> of() = MyCrudRepository(T::class.java)
}
fun createTypeInstance() = type::class.createInstance()
}

Protected inline method in parent class can't access other protected methods

I am having a problem getting IllegalAccessError for the following example:
I have a base class declared in a gradle module called arch
abstract class BaseClass {
protected abstract val value: Int
fun run() {
Log.d("Printme", "value $value")
}
protected inline fun getMyValue(): Lazy<Int> = lazy {
getAnEight()
}
protected fun getAnEight() = 8
}
and a child class declared in gradle module called app
class ChildClass: BaseClass() {
override val value by getMyValue()
}
It is worth saying I am creating a Kotlin project using Android Studio, but these classes are all simple Kotlin objects without any Android specific references. Of course these two modules also have different packages.
Now, from my main entry method I am doing the following (inside app module)
ChildClass().run()
I am calling my run() method declared in base class, which is accessing lazy initiated value property, which is in turn calling getAnEight() method. Since all methods are protected I would expect there is no reason a child class can't call all these. Even if one of the methods is marked as inline and this call gets replaced with method contents, it should still be able to call getAnEight() just fine.
Instead I am receiving IllegalAccessError saying BaseClass.getAnEight() is inaccessible to class ChildClass$$special$$inlined$getMeValue$1. This problem disappears when I remove inline modifier, or if I place BaseClass in the same package as ChildClass.
Is this a bug in Kotlin compiler? Or can someone explain to me this behavior if it's working as intended? Thanks in advance!
https://kotlinlang.org/docs/reference/inline-functions.html#public-inline-restrictions
When an inline function is public or protected and is not a part of a
private or internal declaration, it is considered a module's public
API. It can be called in other modules and is inlined at such call
sites as well.
This imposes certain risks of binary incompatibility caused by changes
in the module that declares an inline function in case the calling
module is not re-compiled after the change.
To eliminate the risk of such incompatibility being introduced by a
change in non-public API of a module, the public API inline functions
are not allowed to use non-public-API declarations, i.e. private and
internal declarations and their parts, in their bodies.
An internal declaration can be annotated with #PublishedApi, which
allows its use in public API inline functions. When an internal inline
function is marked as #PublishedApi, its body is checked too, as if it
were public.
EDIT: I made some bytecode research. The problem is that protected getMyValue() function is inlined into public constructor. In decompiled bytecode, ChildClass public constructor has a following line:
Lazy var4 = LazyKt.lazy((Function0)(new ChildClass$$special$$inlined$getMyValue$1(this)));
As you can see, it creates an instance of class ChildClass$$special$$inlined$getMyValue$1. Let's look at its declaration:
public final class ChildClass$$special$$inlined$getMyValue$1 extends Lambda implements Function0 {
final BaseClass this$0;
public ChildClass$$special$$inlined$getMyValue$1(BaseClass var1) {
super(0);
this.this$0 = var1;
}
public Object invoke() {
return this.invoke();
}
public final int invoke() {
return this.this$0.getAnEight(); // Here lies the problem
}
}
When you create a ChildClass instance, its constructor only creates a ChildClass$$special$$inlined$getMyValue$1 instance, that does not throw any errors. But when you call run(), invoke() method of class above is called. This method is public, its class is public, constructor was public, but getAnEight method is protected. That's how we get this error.

Is there a way to get the type of object that inherits an interface (or another class) in Kotlin?

I've got an interface IMyInterface with a method
fun myMethod(thing: T){}
I also have a class
class MyClass : IMyInterface{}
What I want is that when I implement the members of the interface it automatically sets the type T to be MyClass. Is there a way of doing that?
So, instead of writing
interface IMyInterface <T>{
fun myMethod(thing: T){}
}
class MyClass: IMyInterface<MyClass>{
override fun myMethod(thing: MyClass){} // <<<-- the type is set because I explicitly set it above
}
I want to have something like this:
interface IMyInterface{
fun myMethod(thing: T){}
}
class MyClass: IMyInterface{
override fun myMethod(thing: MyClass){} // <<<-- the template type <T> of the interface is resolved by the compiler by checking what type I provided in method signature (
}
Or maybe getting a type of the class implementing an abstract class.
What you are wanting to do is not possible. You want the compiler to "Magically" figure out what the template parameter is... think about it; how would it know - there is a potentially infinite subset of IMyInterface. It is not implied in your interface that the template type <T> is even of type IMyInterface, so it could literally be any type...
Here is another angle on the problem that may make it clear why the compiler cannot do this:
// The same interface as your example, but with extra method
interface IMyInterface{
fun myMethod(thing: T){}
fun myOtherMethod(thing: T){}
}
// The same implementation as before, except the extra method is overridden with a different type than the first method
class MyClass: IMyInterface{
// the template type <T> of the interface is resolved by the compiler by
// checking what type I provided in method signature (this is what you want compiler to do)
override fun myMethod(thing: MyClass){}
// Uh oh! How does the copmpiler resolve this? We just figured out that <T> was my class.
// So this method won't compile... why not just tell entire class what <T> is
// rather than trying to make all method signatures match up so the compiler can "infer" the type???
override fun myOtherMethod(thing: MyOtherClass) {}
}
class MyOtherClass : IMyInterface {
override fun myMethod(thing: MyOtherClass) = this
override fun myOtherMethod(thing: MyOtherClass) = this
}
There is another problem which Thomas Cook's answer doesn't cover: even if this was possible, you run into major problems with subtyping in at least two ways.
Let's assume a keyword Self which means what you want and
interface IMyInterface{
fun myMethod(thing: Self): Unit
}
Problem 1: You have a val x: IMyInterface = ... What can you pass to x.myMethod? Certainly not any IMyInterface, that would defeat the purpose. But the only thing which is guaranteed to have the same concrete type as x is... x (assuming no Self-returning methods).
Problem 2: Add class MySubClass : MyClass. It must have override fun myMethod(thing: MySubClass), right? But it also has to inherit override fun myMethod(thing: MyClass) from MyClass.