Kotlin: Visibility of static nested Java class declared inside a non-visible class - kotlin

Using java my static-nested java class is visible, but using Kotlin it is not. See my example below. Is there a good reason it is not allowed, or is it a bug? And are there any workarounds so that I can extend NestedStaticClass from Kotlin?
I have a package-private java class containing the static-nested class
package javapackage;
class HiddenClass {
public static class NestedStaticClass {}
}
HiddenClass is extended by a public class.
package javapackage;
public class VisibleClass extends HiddenClass{}
From my java class extending VisibleClass, I can see NestedStaticClass (It compiles)
package otherpackage;
import javapackage.VisibleClass;
public class JavaClass extends VisibleClass {
public static class C4 extends NestedStaticClass {}
public JavaClass() {
new NestedStaticClass();
}
}
But from Kotlin this does not work. I get the compile error: "Unresolved reference NestedStaticClass"
package otherpackage
import javapackage.VisibleClass
class KotlinClass() : VisibleClass() {
class C1() : NestedStaticClass()
init {
val v = NestedStaticClass()
}
}

Related

Kotlin's "internal" keyword Java interop

I'm trying to figure out what happens with internal classes when seen from Java's perspective.
Found this in the docs:
Members of internal classes go through name mangling, to make it harder to accidentally use them from Java and to allow overloading for members with the same signature that don’t see each other according to Kotlin rules
So I was very curious to see how it looks like in practice.
I created a simple Kotlin class:
internal class Foo(i : Int) {}
Built a project, unpacked the jar and used javap to have a look at the actual class... and it displayed a standard public class with the original name:
Compiled from "Foo.kt"
public final class Foo {
public Foo(int);
}
Am I missing something? or is it just the docs that are misleading?
Docs mention members of internal classes, but I tried that as well:
internal class Foo(someInt : Int) {
var someString : String
get() {
TODO()
}
set(value) {}
fun foo() { }
class Bar { }
}
And got the expected output:
Compiled from "Foo.kt"
public final class Foo {
public Foo(int);
public final java.lang.String getSomeString();
public final void setSomeString(java.lang.String);
public final void foo();
}
and:
Compiled from "Foo.kt"
public final class Foo$Bar {
public Foo$Bar();
}

How to get reference to static class of Java super class in Kotlin

I've got sample third party Java code:
public class ApiClass extends PackagePrivateClass {
}
abstract class PackagePrivateClass {
public static class StaticClass {
}
}
So only ApiClass and StaticClass are public. In Java I can get reference to StaticClass with: ApiClass.StaticClass. For the same code in Kotlin I got Unresolved reference: StaticClass. I can't also get reference via PackagePrivateClass, because it's package private (captain obvious). Is there any hack to get reference to StaticClass (it's third party code so I can't simply make PackagePrivateClass public)?
I understand that it's probably 'by design', however it forbids me from using 3p code
It seems the only solution is to build Java wrapper class that your kotlin class can access to.
public class ApiClass extends PackagePrivateClass {
}
abstract class PackagePrivateClass {
public static class StaticClass {
void instanceFunction() {
}
static void classFunction() {
}
}
}
The adapter java class (StaticClassAdapter.java):
class StaticClassAdapter {
private static ApiClass.StaticClass staticClass;
void instanceFunction() {
staticClass.instanceFunction();
}
static void classFunction() {
PackagePrivateClass.StaticClass.classFunction();
}
}
So in your kotlin code...
class KotlinClass {
fun main() {
StaticClassAdapter().instanceFunction()
StaticClassAdapter.classFunction()
}
}

How to access the public variable in plugin1 from plugin2 using OSGI framework

I'm new to OSGI framework and I'm trying to access the 'Derived' Class variable 'publicVariable' from another class 'Derived2' like "Derived.publicVariable" but publicVariable is always shows null. I really appreciate if someone can help me out with this.
Thanks
Manifest file - Derived2
Require-Bundle:com.xxxxxx.Derived1
Java code
abstract class Base {
protected Vector <String> supportedCommands = new Vector <String> ();
protected abstract void initialiseCommands();
}
class Derived extends Base {
private static Derived derivedPlugin = null;
public Derived()
{
derivedPlugin = this;
}
public static Derived getPlugin()
{
return derivedPlugin;
}
public String publicVariable = null;
protected void initialiseCommands()
{
publicVariable = "someData";
System.out.println("Derived" + publicVariable);
}
}
class Derived2 extends Base {
protected void initialiseCommands()
{
supportedCommands.add(Derived.getPlugin().publicVariable);
System.out.println("IMRSAUtilitiesPlugin" +supportedCommands);
}
Also referred below link, which is a similar issue but i'm not using any static variable, it is just a public variable.
how use Singleton object in different class loader....?
The code in the question will not compile. You are trying to access an instance field (publicVariable in class Derived) in a static way, i.e. Derived.publicVariable.
OSGi does not change the semantics of the Java language, and if you cannot even compile your code then OSGi will certainly not be able to run it.

What is the difference between 'open' and 'public' in Kotlin?

I am new to Kotlin and I am confused between open and public keywords. Could anyone please tell me the difference between those keywords?
The open keyword means “open for extension“ - i.e. it's possible to create subclasses of an open class:
The open annotation on a class is the opposite of Java's final: it allows others to inherit from this class. By default, all classes in Kotlin are final, which corresponds to Effective Java, Item 17: Design and document for inheritance or else prohibit it.
You also need to be explicit about methods you want to make overridable, also marked with open:
open class Base {
open fun v() {}
fun nv() {}
}
The public keyword acts as a visibility modifier that can be applied on classes, functions, member functions, etc. If a top-level class or function is public, it means it can be used from other files, including from other modules. Note that public is the default if nothing else is specified explicitly:
If you do not specify any visibility modifier, public is used by default, which means that your declarations will be visible everywhere
class A { ... } in Java is equal to open class A { ... } in Kotlin.
final class B { ... } in Java is equal to class B { ...} in Kotlin.
It is not related with public.
In Kotlin, everything without access modifiers is public by default. You can explicitly say public in the definition, but it is not necessary in Kotlin.
So,
public class A { ... }
and
class A { ... }
are the same in Kotlin.
I put here just for my memo, maybe useful for someone else :
open class in kotlin means that a class can be inherited because by default they are not:
class Car{....}
class Supercar:Car{....} : // give an error
open Car2{....}
class Supercar:Car2{....} : // ok
public class in Java is about the visibility of class (nothing to do with inheritance : unless a class in java is final, it can be inherited by default).
In kotlin all the class are public by default.
open method in kotlin means that the method can be overridden, because by default they are not.
Instead in Java all the methods can be overridden by default
The method of an open class cannot be overridden by default as usual (doesn't matter if the class is open), they must be declared that they can be overridden :
open class Car{
fun steering{...}
}
class Supercar:Car{
override fun steering {...} // give an error
}
open class Car2{
open fun steering{...}
}
class Supercar:Car2{
override fun steering {...} // ok
}
for more details : https://kotlinlang.org/docs/reference/classes.html
public: public keyword in Kotlin is similar to java it is use to make the visibility of classes, methods, variables to access from anywhere.
open: In Kotlin all classes, functions, and variables are by defaults final, and by inheritance property, we cannot inherit the property of final classes, final functions, and data members. So we use the open keyword before the class or function or variable to make inheritable that.
open is opposite to Final in java.
If the class is not 'open', it can't be inherited.
class First{}
class Second:First(){} // Not allowed. Since 'First' is Final(as in Java) by default. Unless marked "open" it can't be inherited
Don't get confused with open and public. public is a visibility modifier
class Third{} // By default this is public
private class Fourth{}
class Fifth{
val third = Third() // No issues
val fourth = Fourth() // Can't access because Fourth is private
}
All classes, methods, and members are public by default BUT not open
Keyword open in kotlin means "Open for Extension"
means if you want any class to be inherited by any subclass or method to be overriden in subclasses you have to mark as open otherwise you will get compile time error
NOTE: abstract classes or methods are open by default you do not need to add explicitly.
OPEN VS FINAL VS PUBLIC
OPEN :
child class can access this because they are inherited by its parent.
In Kotlin you need to add 'open' keyword unlike java whose all classes are 'open' by default
Example :
Kotlin : open class A () {}
Java : class A () {}
FINAL :
child class can't access or inherit.
In JAVA you need to add 'final' keyword unlike kotlin whose all classes are 'final' by default
Example :
Kotlin : class A () {}
Java : final class A () {}
PUBLIC : Any class whether its inherited or not can access its data or methods.
Example in Kotlin :
//Final
class DemoA() {
protected fun Method() {
}
}
class DemoB() : DemoA {
Method() // can't access
}
//OPEN
open class DemoA() {
protected fun Method() {
}
}
class DemoB() : DemoA {
Method() // can access
}
//Public
class DemoA() {
fun Method() {
}
}
class DemoB() {
val a = DemoA()
a.Method() // can access
}
Example in Java :
//FINAL
final class DemoA() {
protected void name() {
}
}
class DemoB() extends DemoA {
name(); // Can't access
}
//Open
class DemoA() {
protected void name() {
}
}
class DemoB() extends DemoA {
name(); // Can access
}
//Public
class DemoA() {
void name() {
}
}
class DemoB(){
DemoA a = new DemoA()
a.name(); // Can access
}
Summarized answer (Kotlin)
The defaults of declarations of classes, methods, and properties are
(public + final). final prevents any inheritance attempts.
In order to be able to extend a class, you must mark the
parent class with the open keyword.
In order to be able to override the methods or properties, you must
mark them in the parent class with the open keyword, in addition to
marking the overriding method or parameter with the override keyword.
public is just encapsulation, it affects the visibility of classes/ methods. Public will make them visible everywhere.
Reference

Jackson mixin selection and inheritance

I have a problem with Jackson mixin and inheritance. I have two target classes, a parent and a child. For those two target classes I have defined two MixIn classes (interfaces) with no inheritance relationship with each other. I also tested with one MixIn interface extending the other but there was no difference in the outcome. When Jackson serializes the parent class it uses the correctly defined mixin for the serialization config and everything works well. However when Jackson serializes the child class it will use the parent class mixin definitions for serializing properties that exist in both the parent and the child class. Then it uses the child class mixin definitions for serializing the properties defined in the child class but not in the parent class. Now this probably has something to do with comparing the base classes or implementing interfaces in Jackson.
Now the question is that is there any way that I could instruct Jackson to use only the mixin definitions for the child class when serializing objects of the child class? And yes I would like to keep both the the mixin definitions in place for two separate use cases so just removing the parent class mixin mapping is not gonna solve my issue.
Example code and expected and actual output JSONs below.
Environment:
Jackson version 2.1.4
Tomcat version 7.0.34.0
Target classes and interfaces they implement:
public interface TestI {
public String getName();
}
public interface TestExtendI extends TestI {
public Integer getAge();
}
public class Test implements TestI {
String name;
public Test(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
public class TestExtend extends Test implements TestExtendI {
private Integer age;
public TestExtend(String name) {
super(name);
}
public TestExtend(String name, Integer age) {
super(name);
this.age = age;
}
#Override
public Integer getAge() {
return age;
}
}
Mixins definitions
public interface TestMixIn {
#JsonProperty("base-name")
public String getName();
}
public interface TestExtendMixIn {
#JsonProperty("ext-name")
public String getName();
#JsonProperty("ext-age")
public Integer getAge();
}
If both mixins are added to the mapper the output JSON is:
{
"base-name": "5", // from parent class mixin definition
"ext-age": 50 // from child class mixin defition
}
With mixin for TestI.class commented everything works as expected and the output JSON is (this is what I would like to achieve):
{
"ext-name": "5", // from child class mixin defition
"ext-age": 50 // from child class mixin defition
}
Object mapper configuration
#Provider
#Produces(MediaType.APPLICATION_JSON)
public class JacksonObjectMapper implements ContextResolver<ObjectMapper> {
private ObjectMapper mapper;
public JacksonObjectMapper() {
mapper = new ObjectMapper();
mapper.addMixInAnnotations(TestI.class, TestMixIn.class);
mapper.addMixInAnnotations(TestExtendI.class, TestExtendMixIn.class);
}
public ObjectMapper getContext(Class<?> type) {
return this.mapper;
}
}
REST api for handling the request/response
#Path("api/test/{id}")
public class TestRestApi {
#GET
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public TestI getTest(#PathParam("id") String id) {
TestI ret = new TestExtend(id, 50);
return ret;
}
}
Solution
As described by pgelinas in the first response the solution to this problem is to define the methods that should be handled by the 'child' mixin again in the child interface. For the example code above that would mean changes to the TestExtendI interface:
public interface TestExtendI extends TestI {
public Integer getAge();
// override the method from the parent interface here
#Override
public String getName();
}
This will solve the issue and doesn't add too much boilerplate code to the solution. Moreover it will not change the interface contracts since the child interface already extends the parent interface.
This is a tricky one; the answer to your specific question is no, you cannot tell a child class to not use the Mixin applied to a parent class.
However, a simple solution to your problem here is to re-declare the getName() method in the TestExtendI interface. I believe MixIn annotation resolution doesn't follow the usual parent-child override (as is the case with normal annotations), but will instead prefer the MixIn that is applied to the class that declares the method. This might be a bug in Jackson or a design choice, you can always fill an issue on github.