Implement setter from java interface as kotlin property - kotlin

I have simple getter and setter for a boolean field in Java interface:
public interface Interface1 {
void setValue1(boolean value);
boolean getValue1();
}
When trying to implement that as a property in a class in Kotlin:
class Class1: Interface1 {
var value1 = false
}
I get the compilation error:
Class 'Class1' is not abstract and does not implement abstract member public abstract fun setValue1(value: Boolean): Unit defined in com.example.Interface1.
So only the getter is overridden. Is it possible to fix that without implementing the both getter and setter manually, without kotlin "sugar"?

https://youtrack.jetbrains.com/issue/KT-6653 says
This is a rather deep issue, unfortunately. It's unlikely that we'll ever make it work the way you'd like
and this stance doesn't seem to have changed since 2015.

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()
}

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.

Why private constructor of sealed class can be called in sub class?

Sealed class in Kotlin can have private constructor only. That means we can call the constructor only in itself:
Sealed classes are not allowed to have non-private constructors (their constructors are private by default).
// `private` and `constructor()` are redundant.
sealed class Expr private constructor()
But, when we utilize sealed class, a sub class have to inherit seald class:
// Above Kotlin 1.1
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
As you can see the code above, sealed class's private constructor is called outside of sealed class itself. When sub class is instantiated, the constructor of parent(sealed class) will be called before sub class's own constructor is called. Is it just exception to visibility modifiers?
https://kotlinlang.org/docs/reference/visibility-modifiers.html#classes-and-interfaces
For members declared inside a class: private means visible inside this class only (including all its members);
Consider the following code:
open class A private constructor(var name: String){
class B : A("B")
class C : A("C")
}
The above code compiles fine, as the constructor is called inside the class A.
If a class D tries to inherit outside A, it won't compile.
class D : A("D") // Error: Cannot access '<init>': it is private in 'A'
As mentioned on the page Sealed class in Kotlin,
A sealed class can have subclasses, but all of them must be declared in the same file as the sealed class itself. (Before Kotlin 1.1, the rules were even more strict: classes had to be nested inside the declaration of the sealed class).
It seems that kotlin relaxed the requirement of nested classes only.
So, the following code works fine in 1.1+ but would fail in earlier versions:
sealed class A(var name: String)
class B : A("B")
class C : A("C")
whereas the following code would have been required in versions before 1.1, which respects the private constructor.
sealed class A (var name: String){
class B : A("B")
class C : A("C")
}
So, allowing private constructors of sealed classes outside the class (but within the same file) can be considered an enhancement to make the code cleaner.
You can figure out what's happening by taking a look at the generated bytecode (you can do this by going to Tools -> Kotlin -> Show Kotlin Bytecode and then choosing Decompile in the pane that appears.). Decompiling it to Java shows this code for the Expr class:
public abstract class Expr {
private Expr() {
}
// $FF: synthetic method
public Expr(DefaultConstructorMarker $constructor_marker) {
this();
}
}
So there is a non-private constructor for the Expr class generated, with a special parameter. Then, as you'd expect, if you look at the decompiled bytecode of Const for example, you'll see that it calls into this constructor:
public final class Const extends Expr {
public Const(double number) {
super((DefaultConstructorMarker)null);
this.number = number;
}
// other fields and methods ...
}
You still can't subclass Expr from Kotlin, because the Kotlin compiler knows that it's a sealed class from the metadata in the file, and will respect that.
As for Java client code, there you can't access this same constructor yourself because the DefaultConstructorMarker is package-private in the kotlin.jvm.internal package that it's in, so even if you write out the import statement for it manually, the compiler won't allow it.
My guess is that the package-private visibility might only be enforced at compile time, and that's why the Kotlin compiler is able to output the bytecode corresponding to the snippet above (not completely sure though).

Explicit inheritance from Any in Kotlin - Can and How is it done?

The Kotlin documentation says that
All classes in Kotlin have a common superclass Any, that is a default super for a class with no supertypes declared
If I try and explicitly inherit from Any:
class MyClass : Any {
}
The compiler gives an error:
Kotlin: This type has a constructor, and thus must be initialized here
I haven't been able to find the documentation for the Any class. Is it possible to explicitly inherit from Any, and if so, what do you pass it?
You have to call the constructor explicitly:
class MyClass : Any()
THe constructor of Any has no parameters, thus to call it you simply provide the empty parentheses
In case we are extending a class,we need to add brackets(for implicit constructor)
class MyClass : Any()
This is similar to calling
class MyClass extends Any
{
MyClass()
{
super();
}
}
But if we are implementing an interface(interface do not have constructors),syntax should be the following
class MyClass : BaseInterface
In case when you have secondary constructor (key word constructor) you can use the next syntax
class MyClass : Any {
constructor() : super()
}
If the class has no primary constructor, then each secondary constructor has to initialize the base type using the super keyword, or to delegate to another constructor which does that.
Read more here - https://kotlinlang.org/docs/reference/classes.html
P.S. your problem could be solved easily using Android Studio feature - Project quick fix (show intention actions and quick fixes) Win - Alt + Enter, Mac - Option + Enter