I need to redefine/override method from java public class in Kotlin class:
// Java
public class BaseOne {
public static void m1() {}
}
// Kotlin
class BaseTwo : BaseOne() {
override fun m1() {}
}
but get an error: m1 overrides nothing.
If I remove override annotation I get Accidental override: The following declarations have the same JVM signature.
In java this works fine, but not in Kotlin :(
UPD: working java code
public class BaseTree extends BaseOne {
public static void m1() {}
}
UPD2 "Curiouser and curiouser!" (с)
I have next code:
// Java class
public class BaseOne {
public static void m1() {
System.out.println("BaseOne");
}
}
// Kotlin class
class BaseTwo : BaseOne() {
companion object {
fun m1() {
println("BaseTwo")
}
}
}
// Java class
public class BaseThree extends BaseOne {
public static void m1() {
System.out.println("BaseThree");
}
}
When I run this code from Java,
public class Main {
public static void main(String[] args) {
BaseOne.m1();
BaseThree.m1();
BaseTwo.m1();
}
}
I receive:
BaseOne
BaseThree
BaseOne
As you see - override/redefine/"hide" doesn't work
But if I run it from Kotlin's main
fun main(args: Array<String>) {
BaseOne.m1()
BaseThree.m1()
BaseTwo.m1()
}
all works as intended:
BaseOne
BaseThree
BaseTwo
My additional question is - How to write code with equal behaviour? Is there a docs about it?
You are override a static method and overriding depends on having an instance of a class.
public class BaseOne {
public void m1() {}
}
Related
This question already has an answer here:
Why can I override a static interface method?
(1 answer)
Closed 1 year ago.
Consider the following snippet:
interface Super{
public static void doIt(){}
}
class Sub implements Super{
public void doIt(){}
}
Here I have declared a static member method and it is being redeclared as the instance method in the child class.
This is allowed by the compiler - but when I do the same with the superclass and subclass types - this gives compilation error:
class Super{
public static void doIt(){}
}
class Sub extends Super{
public void doIt(){}
}
What is the rationale behind the same? - ideally the way to access the subclass is essentially the same - then why this restriction?
The reason for this is that Java allows invoking static methods in a non-static manner. Consider this example:
public class MyClass {
public static void sayHello() {
}
public void test() {
this.sayHello();
}
}
This will produce a compiler warning (The static method sayHello() from the type MyClass should be accessed in a static way), but it will compile and invoke the static method correctly at runtime.
That's why the following code will not compile because of an ambiguity (Duplicate method test() in type MyClass):
public class MyClass {
public static void test() {
}
public void test() {
}
}
The reason for the compile error is, that if you write the following, the compiler cannot know which method to invoke, because it allows to call static methods in a non-static manner:
public class MyClass {
public static void test() {
}
public void test() {
}
public void execute() {
this.test();
}
}
For the same reason it is not possible to have the static test() method in the parent class - the same rules apply. It is possible in Java to call static methods of super classes with or without qualification:
public class Super {
public static void test() {
}
}
public class Sub extends Super {
public void execute() {
this.test();
}
}
OR
public class Sub {
public void execute() {
test();
}
}
where the invocation of this.test() will produce a warning, but will work at runtime.
For static methods in interfaces, the above example will not work, because the compiler forces you to call the static method of the interface in a qualified manner (edit: because they are not being inherited). The following will not work (The method interfaceStatic() is undefined for the type Sub):
public interface Interface {
public static void interfaceStatic() {
}
}
public class Sub implements Interface {
public void test() {
interfaceStatic();
}
}
In order to call interfaceStatic() the invocation has to be qualified like this:
public class Sub implements Interface {
public void test() {
Interface.interfaceStatic();
}
}
That's the difference between defining the static method in an interface and defining it in the super class: The way of invocation. If you implement multiple interfaces which all have a static method with the same signature, the compiler cannot know which one to call.
This is the reason why it is allowed to define a static method with the same signature in an implemented interface, but not in the parent classes.
I'm trying to write a factory class that takes in a class inherited from a specific abstract base class and calls a static method on that class to perform some logic and data manipulation before creating one or more instances of that class based on that manipulated data. So far, this is what I have:
public abstract class Foobar {
public static void sayHi() {}
}
public class Foo extends Foobar {
public static void sayHi() {
System.out.println("Hi from Foo!");
}
}
public class Bar extends Foobar {
public static void sayHi() {
System.out.println("Hi from Bar!");
}
}
public class PolymorphicFoobar {
public PolymorphicFoobar(Class<Foobar> cls) {
// Do some logic before creating an instance
cls.sayHi();
}
}
class Playground {
public static void main(String[ ] args) {
// Neither works
new PolymorphicFoobar(Foo.class);
new PolymorphicFoobar((Class<Foobar>)Bar.class);
}
}
You can do it with reflection and a capture-of wildcard; like
public PolymorphicFoobar(Class<? extends Foobar> cls) {
try {
Method sayHi = cls.getMethod("sayHi");
sayHi.invoke(cls);
} catch (Exception e) {
e.printStackTrace();
}
}
And then to invoke it, the syntax is very similar to what you had (you're missing new, but otherwise the first form is good). Like,
public static void main(String[] args) {
new PolymorphicFoobar(Foo.class);
new PolymorphicFoobar(Bar.class);
}
Outputs
Hi from Foo!
Hi from Bar!
How to use a non-abstract method from an abstract class in another class without extending?
Abstract Class:
package com.test;
public abstract class MyAbstract {
public abstract void abstractMethod();
public void callNonAbstractMethod() {
System.out.println("Hello");
}
}
The anonymous class:
package com.test;
public class Example {
public static void main(String[] args) {
new Example().something();
}
void something() {
MyAbstract a = new MyAbstract() {
#Override
public void abstractMethod() {
//TODO implement
}
};
a.callNonAbstractMethod();
}
}
Internal class generated by the compiler would be for above example.
static class Example extends MyAbstract
{
Example(){}
void abstractMethod()
{
System.out.println("hiee");
}
}
Abstract Class:
package com.test;
public abstract class MyAbstract {
public abstract void abstractMethod();
public void callNonAbstractMethod() {
System.out.println("Hello");
}
}
You can't.
To call any non-static method of some class A, you need an instance of A or of a subclass of A, as such a method typically operates on data within such an instance. That's at the very core of what "object-oriented" is all about.
In your case, A is abstract and can't have direct instances. So the only way to call your method is to have some instance of some class B that extends A. You can either find an existing subclass that you can use, or create your own subclass.
I think you can use an anonymous class. Although it is a kind of extension, you are not explicitly using the keyword extends. In fact, you cannot use any class in java without implicitly extending because every class extends Object.
package com.test;
public class Example {
public static void main(String[] args) {
new Example().something();
}
void something() {
MyAbstract a = new MyAbstract() {
#Override
public void abstractMethod() {
//TODO implement
}
};
a.callNonAbstractMethod();
}
}
and here's your abstract class:
package com.test;
public abstract class MyAbstract {
public abstract void abstractMethod();
public void callNonAbstractMethod() {
System.out.println("Hello");
}
}
results in:
Hello
I am trying to provide a callback to a class function written in Java by means of an anonymous abstract class instance, but from a groovy class. The code below illustrate my issue.
//Java Code
abstract class CallBackWrapper
{
int someAttr, someOtherAttr;
public abstract void execute();
public int getAttr()
{
return someAttr;
}
}
class Delegator
{
public void callExecute(CallBackWrapper w)
{
w.execute();
}
}
//Groovy Code
class GroovyClass
{
private void foo()
{
//Doesn't work
Delegator d = new Delegator();
d.callExecute(new CallBackWrapper() {
public void execute() {
System.out.println("Hello World");
}
});
//Also doesn't work
Delegator d = new Delegator();
d.callExecute([execute:{println "HELLO from Groovy"}] as CallBackWrapper)
}
}
The closest I got to getting it to work is by changing CallBackWrapper to an interface AND declaring it inside the Groovy class. However, I need an abstract class. My question is, how can I implement this callback behavior from "Groovy Land" so that the Java class understands? Currently I get Groovy runtime errors that are not very helpful in explaining the true nature of the issue.
You haven't specified your error, but I tried your code here and got the following error:
$ javac *.java && groovy GroovyClass.groovy && rm *.class
Caught: java.lang.IllegalAccessError: class GroovyClass$1 cannot access its superclass CallBackWrapper
java.lang.IllegalAccessError: class GroovyClass$1 cannot access its superclass CallBackWrapper
It happened due to Groovy's generated inner class being unable to access CallBackWrapper. I added the public modifier and it worked fine:
// Delegator.java
class Delegator {
public void callExecute(CallBackWrapper w) {
w.execute();
}
}
// CallBackWrapper.java
public abstract class CallBackWrapper {
int someAttr, someOtherAttr;
public abstract void execute();
public int getAttr()
{
return someAttr;
}
}
// GroovyClass.groovy
class GroovyClass
{
private void foo() {
def d = new Delegator()
d.callExecute { println "Hello from groovy" }
}
static main(args) {
new GroovyClass().foo()
}
}
Out of curiosity, I added Delegator::me() to Java code, invoked it from Groovy and it worked:
class Delegator {
public void callExecute(CallBackWrapper w) {
w.execute();
}
void me() {
new CallBackWrapper() {
public void execute() {
System.out.println("Echo");
}
}.execute();
}
}
Seems to me like a bug similar to this one. You could fill a jira.
I have a class in jar of which I want to invoke a method. But that method has parameter of abstract class and that abstract class is inner method of class in jar. AbstractClassA is a HIDDEN class. Here is code:
public class A{
private invokeThisMethod(AbstractClassA object){
}
public abstract class AbstractClassA {
public void update(int remaining){}
}
}
public class myClass{
//using Reflection get object of class A
objectOfClassAusingReflection.inovke("invokeThisMethod", params)
}
Problem here is how do I create concrete implementation of AbstractClassA to pass in invoke method and get update method callbacks ?
Something like this should work:
AbstractClassA a = new AbstractClassA() {
public void update(int remaining) {... do something...}
};
objectOfClassAusingReflection.inovke("invokeThisMethod", a);
You cannot create an instance of abstract class or any interface at runtime.
Instead create an anonymous class for this.
public abstract class A {
public void fun(){....}
public abstract void absFun();
}
public class MyClass {
objectOfClassA = new A(){
public void absFun(){...}
}
}
Or you can first create implementation for that abstract classes for which you will have to create another class extending A
class AWrapper extends A {
public class ImplementationClassA extends AbstractClassA {
// override abstract functions...
}
}
Now you can use this Awrapper class
AWrapper wrapperObj = new AWrapper();
A obj = wrapperObj; // just to make it clear that A can hold wrapperObj as it is implementation of it.
A.AbstractClassA absObj = wrapperObj.new ImplementationClassA();
...
objectOfClassAusingReflection.inovke("invokeThisMethod", params)
Below code should work--
Here, i used anonymus classes for both outer and inner class and then with the help of getdeclatedMethod called your update method.
"TestAbs" is your jar class--
public abstract class TestAbs {
private void invokeThisMethod(AbstractClassA object) {
}
public abstract class AbstractClassA {
public void update(int remaining) {
}
}
}
Then calling your jar class from "TestAbs1" like below--
public class TestAbs1 {
public static void main(String[] args) {
TestAbs.AbstractClassA abs = new TestAbs() {
AbstractClassA a = new AbstractClassA() {
public void update(int remaining) {
System.out.println("Inside update method : " + remaining);
}
};
}.a;
try {
int i = 1;
Class<?> class1 = Class.forName("app.test.mytest.TestAbs$AbstractClassA"); -- (*Getting instance of inner class*)
System.out.println(class1.getDeclaredMethod("update", int.class));
class1.getDeclaredMethod("update", int.class).invoke(abs, i);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The output i got is --
public void app.test.mytest.TestAbs$AbstractClassA.update(int)
Inside update method : 1
Answer to your Comment:-
What I understood from your comment is that, you wanted to call method from abstractClass which is hidden in outerclass.
As per my understanding, there is one way like below--
public abstract class TestAbs {
private void invokeThisMethod(AbstractClassA object) {
}
private abstract class AbstractClassA { --- your hidden class
public void update(int remaining) {
}
}
public class ImplementedClass extends AbstractClassA{ -- use implemented class here
....
...
}
}
And after that, use your ImplementedClass the same way mentioned above.
You can find reference example for private inner class here from java docs.
Note: In your question context, since your inner class and outer class is in jar, so I think it is difficult for you add implementation class in your jar.
In case, you find any alternatives, please let all knows about this;
thanks.