Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot override overloaded method #63

Closed
mhofman opened this issue May 8, 2015 · 8 comments
Closed

Cannot override overloaded method #63

mhofman opened this issue May 8, 2015 · 8 comments
Assignees
Labels
Milestone

Comments

@mhofman
Copy link

mhofman commented May 8, 2015

According to the documentation it's possible to extend a Java Class with overloaded methods and override such method from JavaScript.

However the runtime doesn't support overriding methods that are overloaded on the type of the argument, or on the number of arguments (see 1st comment).

Extending such a Java class will only override the first method overload.
Similarly, implementing an interface with such overloaded methods will cause a java.lang.AbstractMethodError to be thrown when attempting to call any method other than the first.

Java:

package org.nativescript.tester;

public class Tester {
    public static interface Logger {
        public void print(byte value);
        public void print(short value); 
        public void print(int value); 
        public void print(long value); 
        public void print(float value); 
        public void print(double value); 
        public void print(char value);
        public void print(Object value);
    }

    public static class DummyLogger implements Logger {

        @Override
        public void print(byte value) {}

        @Override
        public void print(short value) {}

        @Override
        public void print(int value) {}

        @Override
        public void print(long value) {}

        @Override
        public void print(float value) {}

        @Override
        public void print(double value) {}

        @Override
        public void print(char value) {}

        @Override
        public void print(Object value) {}

    }

    public static class Parent {
        public void foo() {

        }
    }

    public static class Child extends Parent {
        @Override
        public void foo() {
            super.foo();
        }
    }

    public static void testLogger(Logger logger) {
        assert logger != null;

        byte b = 1;
        short s = 2; 
        int i = 3; 
        long l = 4; 
        float f = 5; 
        double d = 6; 
        char c = 'a';
        Object o = new Object();
        Throwable t = new UnsupportedOperationException("Not implemented.");
        String str = "Hello";
        Parent parent = new Parent();
        Child child = new Child();
        Parent childAsParent = new Child();

        logger.print(b);
        logger.print(s);
        logger.print(i);
        logger.print(l);
        logger.print(f);
        logger.print(d);
        logger.print(c);
        logger.print(o);
        logger.print(t);
        logger.print(str);
        logger.print(parent);
        logger.print(child);
        logger.print(childAsParent);
    }
}

Javascript:

var Tester = org.nativescript.tester.Tester;

function testLogger(loggerName, logger) {
    var err;
    console.log('Trying ' + loggerName + ' logger');
    try {
        Tester.testLogger(logger);
    } catch(e) {
        err = e;
    }
    console.log('Done with ' + loggerName + ' logger', 'error=', err);
}

function print(value) {
    console.log('type=', typeof value, 'value=', value);
}

testLogger('native dummy', new Tester.DummyLogger());

var JSDummyLogger = Tester.DummyLogger.extend({
    print: print
});

testLogger('js dummy', new JSDummyLogger());

testLogger('js pure', new Tester.Logger({
    print: print
}));

Log output:

D/TNS.Native( 4999): MetadataNode::GetterCallback: prop 'tester' for node 'nativescript' called, nodeType=0, hash=579262823
D/TNS.Native( 4999): MetadataNode::GetterCallback: prop 'Tester' for node 'tester' called, nodeType=0, hash=778677259
D/TNS.Native( 4999): RegisterInstance called for 'org/nativescript/tester/Tester$DummyLogger-'
D/TNS.Native( 4999): RegisterInstance: Linking new instance
D/TNS.Native( 4999): Linking js object: 202244621 and java instance id: 98
D/TNS.Native( 4999): CreateJavaInstance:  org/nativescript/tester/Tester$DummyLogger-0
D/TNS.Native( 4999): GetCachedConstructorId: encodedCtorArgs=org/nativescript/tester/Tester$DummyLogger-.I.<init>.0, ctorId=14
D/TNS.Java( 4999): MakeInstanceStrong (98, class org.nativescript.tester.Tester$DummyLogger)
D/TNS.Java( 4999): Platform.getJavaObjectByID:98
D/TNS.Native( 4999): RegisterInstance: Updating linked instance with its real class
D/TNS.Native( 4999): SetClass called
D/TNS.Native( 4999): ObjectManager::GetJSInstanceInfo: called
D/TNS.Native( 4999): MetadataNode::GetterCallback: prop 'util' for node 'android' called, nodeType=0, hash=468975101
D/TNS.Native( 4999): MetadataNode::GetterCallback: prop 'Log' for node 'util' called, nodeType=0, hash=733581938
D/TNS.Native( 4999): CallJavaMethod called android/util/Log.v. static method
V/JS      ( 4999): Trying native dummy logger
D/TNS.Native( 4999): CallJavaMethod called org/nativescript/tester/Tester.testLogger. static method
D/TNS.Native( 4999): ObjectManager::GetJSInstanceInfo: called
D/TNS.Native( 4999): CallJavaMethod called android/util/Log.v. static method
V/JS      ( 4999): Done with native dummy logger error=
D/TNS.Native( 4999): ExtendsCallMethodHandler: called with
D/TNS.Native( 4999): ExtendsCallMethodHandler: extend full name org/nativescript/tester/Tester$DummyLogger-f--main-view-model-l42-c44--
D/TNS.Native( 4999): RegisterInstance called for 'com/tns/gen/org/nativescript/tester/Tester$DummyLogger-f--main-view-model-l42-c44--'
D/TNS.Native( 4999): RegisterInstance: Linking new instance
D/TNS.Native( 4999): Linking js object: 41699439 and java instance id: 99
D/TNS.Native( 4999): CreateJavaInstance:  com/tns/gen/org/nativescript/tester/Tester$DummyLogger-f--main-view-model-l42-c44--
D/TNS.Native( 4999): ObjectManager::GetJSInstanceInfo: called
D/TNS.Native( 4999): GetJSInstanceInfo: need to check prototype :871280876
D/TNS.Native( 4999): superValue.GetPrototype=536300692
D/TNS.Java( 4999): Looking for proxy file: /data/data/org.nativescript.helloworld/code_cache/secondary-dexes/org.nativescript.tester.Tester_DummyLogger-f--main-view-model-l42-c44---1431060602146-1.dex Result: NOT Found. Proxy Gen needed. ClassName: com.tns.gen.org.nativescript.tester.Tester_DummyLogger-f--main-view-model-l42-c44--
D/TNS.Java( 4999): generating proxy in place
D/TNS.Rungime.Proxy.Generator( 4999): generatingMethod print
D/Generator( 4999): Saving proxy with file name: org.nativescript.tester.Tester_DummyLogger-f--main-view-model-l42-c44---1431060602146-1
D/TNS.Java( 4999): Finished inplace gen took: 8.204938ms
D/TNS.Java( 4999): TotalGenTime:  78.638441ms
I/dex2oat ( 5042): /system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --instruction-set=x86 --instruction-set-features=default --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --dex-file=/data/data/org.nativescript.helloworld/code_cache/secondary-dexes/org.nativescript.tester.Tester_DummyLogger-f--main-view-model-l42-c44---1431060602146-1.dex --oat-fd=28 --oat-location=/data/data/org.nativescript.helloworld/code_cache/secondary-dexes/odex/org.nativescript.tester.Tester_DummyLogger-f--main-view-model-l42-c44---1431060602146-1.dex --runtime-arg -Xms64m --runtime-arg -Xmx512m
I/dex2oat ( 5042): dex2oat took 11.631ms (threads: 1) arena alloc=31KB java alloc=13KB native alloc=470KB free=3MB
D/TNS.Java( 4999): Finished injecting into multidex: /data/data/org.nativescript.helloworld/code_cache/secondary-dexes/org.nativescript.tester.Tester_DummyLogger-f--main-view-model-l42-c44---1431060602146-1.dex took: 52.100999ms
D/TNS.Java( 4999): TotalMultiDexTime: 223.368387ms
D/TNS.Java( 4999): Finished loading class : com.tns.gen.org.nativescript.tester.Tester_DummyLogger-f--main-view-model-l42-c44-- took: 52.100999ms
D/TNS.Java( 4999): TotalLoadDexTime: 6.449988ms
D/TNS.Native( 4999): GetCachedConstructorId: encodedCtorArgs=com/tns/gen/org/nativescript/tester/Tester$DummyLogger-f--main-view-model-l42-c44--.I.<init>.0, ctorId=15
D/TNS.Java( 4999): MakeInstanceStrong (99, class com.tns.gen.org.nativescript.tester.Tester_DummyLogger-f--main-view-model-l42-c44--)
D/TNS.Java( 4999): MakeInstanceStrong (99, class com.tns.gen.org.nativescript.tester.Tester_DummyLogger-f--main-view-model-l42-c44--)
D/TNS.Java( 4999): Platform.getJavaObjectByID:99
D/TNS.Native( 4999): RegisterInstance: Updating linked instance with its real class
D/TNS.Native( 4999): SetClass called
D/TNS.Native( 4999): ObjectManager::GetJSInstanceInfo: called
D/TNS.Native( 4999): CallJavaMethod called android/util/Log.v. static method
V/JS      ( 4999): Trying js dummy logger
D/TNS.Native( 4999): CallJavaMethod called org/nativescript/tester/Tester.testLogger. static method
D/TNS.Native( 4999): ObjectManager::GetJSInstanceInfo: called
D/TNS.Java( 4999): Platform.CallJSMethod: calling js method print with javaObjectID 99 type=com.tns.gen.org.nativescript.tester.Tester_DummyLogger-f--main-view-model-l42-c44--
D/TNS.Native( 4999): CallJSMethodNative called javaObjectID=99
D/TNS.Native( 4999): CallJSMethodNative called jsObject=41699439
D/TNS.Native( 4999): implementationObject->GetIdentityHash()=41699439
D/TNS.Native( 4999): CallJavaMethod called android/util/Log.v. static method
V/JS      ( 4999): type= number value= 1
D/TNS.Native( 4999): CallJavaMethod called android/util/Log.v. static method
V/JS      ( 4999): Done with js dummy logger error=
D/TNS.Native( 4999): RegisterInstance called for 'com/tns/gen/org/nativescript/tester/Tester$Logger-f--main-view-model-l48-c27--'
D/TNS.Native( 4999): RegisterInstance: Linking new instance
D/TNS.Native( 4999): Linking js object: 916644032 and java instance id: 100
D/TNS.Native( 4999): CreateJavaInstance:  com/tns/gen/org/nativescript/tester/Tester$Logger-f--main-view-model-l48-c27--
D/TNS.Java( 4999): Looking for proxy file: /data/data/org.nativescript.helloworld/code_cache/secondary-dexes/org.nativescript.tester.Tester_Logger-f--main-view-model-l48-c27---1431060602146-1.dex Result: NOT Found. Proxy Gen needed. ClassName: com.tns.gen.org.nativescript.tester.Tester_Logger-f--main-view-model-l48-c27--
D/TNS.Java( 4999): generating proxy in place
D/TNS.Rungime.Proxy.Generator( 4999): generatingMethod print
D/Generator( 4999): Saving proxy with file name: org.nativescript.tester.Tester_Logger-f--main-view-model-l48-c27---1431060602146-1
D/TNS.Java( 4999): Finished inplace gen took: 6.910072ms
D/TNS.Java( 4999): TotalGenTime:  85.548513ms
I/dex2oat ( 5045): /system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --instruction-set=x86 --instruction-set-features=default --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --dex-file=/data/data/org.nativescript.helloworld/code_cache/secondary-dexes/org.nativescript.tester.Tester_Logger-f--main-view-model-l48-c27---1431060602146-1.dex --oat-fd=28 --oat-location=/data/data/org.nativescript.helloworld/code_cache/secondary-dexes/odex/org.nativescript.tester.Tester_Logger-f--main-view-model-l48-c27---1431060602146-1.dex --runtime-arg -Xms64m --runtime-arg -Xmx512m
I/dex2oat ( 5045): dex2oat took 13.712ms (threads: 1) arena alloc=21KB java alloc=9KB native alloc=468KB free=3MB
D/TNS.Java( 4999): Finished injecting into multidex: /data/data/org.nativescript.helloworld/code_cache/secondary-dexes/org.nativescript.tester.Tester_Logger-f--main-view-model-l48-c27---1431060602146-1.dex took: 30.681025ms
D/TNS.Java( 4999): TotalMultiDexTime: 254.049412ms
D/TNS.Java( 4999): Finished loading class : com.tns.gen.org.nativescript.tester.Tester_Logger-f--main-view-model-l48-c27-- took: 30.681025ms
D/TNS.Java( 4999): TotalLoadDexTime: 6.774333ms
D/TNS.Native( 4999): GetCachedConstructorId: encodedCtorArgs=com/tns/gen/org/nativescript/tester/Tester$Logger-f--main-view-model-l48-c27--.I.<init>.1.org/nativescript/tester/Tester$Logger, ctorId=16
D/TNS.Java( 4999): MakeInstanceStrong (100, class com.tns.gen.org.nativescript.tester.Tester_Logger-f--main-view-model-l48-c27--)
D/TNS.Java( 4999): MakeInstanceStrong (100, class com.tns.gen.org.nativescript.tester.Tester_Logger-f--main-view-model-l48-c27--)
D/TNS.Java( 4999): Platform.getJavaObjectByID:100
D/TNS.Native( 4999): RegisterInstance: Updating linked instance with its real class
D/TNS.Native( 4999): SetClass called
D/TNS.Native( 4999): ObjectManager::GetJSInstanceInfo: called
D/TNS.Native( 4999): CallJavaMethod called android/util/Log.v. static method
V/JS      ( 4999): Trying js pure logger
D/TNS.Native( 4999): CallJavaMethod called org/nativescript/tester/Tester.testLogger. static method
D/TNS.Native( 4999): ObjectManager::GetJSInstanceInfo: called
D/TNS.Java( 4999): Platform.CallJSMethod: calling js method print with javaObjectID 100 type=com.tns.gen.org.nativescript.tester.Tester_Logger-f--main-view-model-l48-c27--
D/TNS.Native( 4999): CallJSMethodNative called javaObjectID=100
D/TNS.Native( 4999): CallJSMethodNative called jsObject=916644032
D/TNS.Native( 4999): implementationObject->GetIdentityHash()=916644032
D/TNS.Native( 4999): CallJavaMethod called android/util/Log.v. static method
V/JS      ( 4999): type= number value= 1
D/TNS.Native( 4999): Error during java interop
E/art     ( 4999): invalid stream - problem with parameter iterator in /data/data/org.nativescript.helloworld/code_cache/secondary-dexes/android.view.View_OnClickListener-fui-button-l27-c42---1431060602146-1.dex for method void com.tns.gen.android.view.View_OnClickListener-fui-button-l27-c42--.onClick(android.view.View)
D/TNS.Native( 4999): Error during java interop errorMessage java.lang.AbstractMethodError: abstract method "void org.nativescript.tester.Tester$Logger.print(short)"
D/TNS.Native( 4999):     org.nativescript.tester.Tester.testLogger(Tester.java:74)
D/TNS.Native( 4999):     com.tns.Platform.callJSMethodNative(Native Method)
D/TNS.Native( 4999):     com.tns.Platform.dispatchCallJSMethodNative(Platform.java:808)
D/TNS.Native( 4999):     com.tns.Platform.callJSMethod(Platform.java:653)
D/TNS.Native( 4999):     com.tns.Platform.callJSMethod(Platform.java:637)
D/TNS.Native( 4999):     com.tns.Platform.callJSMethod(Platform.java:627)
D/TNS.Native( 4999):     com.tns.gen.android.view.View_OnClickListener-fui-button-l27-c42--.onClick(android.view.View$OnClickListener.java)
D/TNS.Native( 4999):     android.view.View.performClick(View.java:4780)
D/TNS.Native( 4999):     android.view.View$PerformClick.run(View.java:19866)
D/TNS.Native( 4999):     android.os.Handler.handleCallback(Handler.java:739)
D/TNS.Native( 4999):     android.os.Handler.dispatchMessage(Handler.java:95)
D/TNS.Native( 4999):     android.os.Looper.loop(Looper.java:135)
D/TNS.Native( 4999):     android.app.ActivityThread.main(ActivityThread.java:5257)
D/TNS.Native( 4999):     java.lang.reflect.Method.invoke(Native Method)
D/TNS.Native( 4999):     java.lang.reflect.Method.invoke(Metho
D/TNS.Java( 4999): MakeInstanceStrong (101, class java.lang.AbstractMethodError)
D/TNS.Native( 4999): Linking js object: 19923542 and java instance id: 101
D/TNS.Native( 4999): CallJavaMethod called android/util/Log.v. static method
V/JS      ( 4999): Done with js pure logger error= Error: java.lang.AbstractMethodError: abstract method "void org.nativescript.tester.Tester$Logger.print(short)"
V/JS      ( 4999):     org.nativescript.tester.Tester.testLogger(Tester.java:74)
V/JS      ( 4999):     com.tns.Platform.callJSMethodNative(Native Method)
V/JS      ( 4999):     com.tns.Platform.dispatchCallJSMethodNative(Platform.java:808)
V/JS      ( 4999):     com.tns.Platform.callJSMethod(Platform.java:653)
V/JS      ( 4999):     com.tns.Platform.callJSMethod(Platform.java:637)
V/JS      ( 4999):     com.tns.Platform.callJSMethod(Platform.java:627)
V/JS      ( 4999):     com.tns.gen.android.view.View_OnClickListener-fui-button-l27-c42--.onClick(android.view.View$OnClickListener.java)
V/JS      ( 4999):     android.view.View.performClick(View.java:4780)
V/JS      ( 4999):     android.view.View$PerformClick.run(View.java:19866)
V/JS      ( 4999):     android.os.Handler.handleCallback(Handler.java:739)
V/JS      ( 4999):     android.os.Handler.dispatchMessage(Handler.java:95)
V/JS      ( 4999):     android.os.Looper.loop(Looper.java:135)
V/JS      ( 4999):     android.app.ActivityThread.main(ActivityThread.java:5257)
V/JS      ( 4999):     java.lang.reflect.Method.invoke(Native Method)
V/JS      ( 4999):     java.lang.reflect.Method.invoke(Method.java:372)
V/JS      ( 4999):     com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
V/JS      ( 4999):     com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
@mhofman mhofman changed the title Cannot override method overloaded on type Cannot override overloaded method May 8, 2015
@mhofman
Copy link
Author

mhofman commented May 8, 2015

I'm getting the same error when overloading on number of arguments.

    public static interface Logger {
        public void print();
        public void print(Object value);
    }

@slavchev
Copy link

Implementing Java interfaces require different syntax. You cannot use extend functions for this purpose. Use new and pass the implementation object as a single constructor parameter. Here is an example from the documentation https://github.com/NativeScript/docs/wiki/Getting-Started-with-NativeScript-for-Android#how-to-implement-an-interface

I will investigate the case with DummyLogger class further.

@slavchev slavchev self-assigned this May 15, 2015
@slavchev slavchev added this to the v1.1. milestone May 15, 2015
@slavchev slavchev added the bug label May 15, 2015
@slavchev slavchev assigned blagoev and unassigned slavchev May 15, 2015
@mhofman
Copy link
Author

mhofman commented May 15, 2015

@slavchev as you can see in my code I do extend the class and new the interface. The code is valid, that's not the problem. It's the runtime that is not behaving right.

@blagoev
Copy link
Contributor

blagoev commented May 15, 2015

Indeed we have identified a bug and a fix is already in the works. Thanks for reporting this.

@blagoev
Copy link
Contributor

blagoev commented May 18, 2015

The master have been updated with the fix for that, closing this issue.

@blagoev blagoev closed this as completed May 18, 2015
@slavchev slavchev added bug and removed bug labels May 19, 2015
@x4080
Copy link

x4080 commented Mar 8, 2016

Hi, I found that implementing firebase CompletionListener is not working :
{ To notify if firebase set is completed, I checked the firebase nativescript plugin is not implementing this function, so I tried it on my own and it failed }

        var complete = com.firebase.client.Firebase.CompletionListener.extend({
            onComplete: function (err, firebase) {
                console.log('complete');
            }
        });

        ref.child(url).setValue(object,new complete);

and here's the firebase android doc for it

public static interface Firebase.CompletionListener
void onComplete(FirebaseError error,
                Firebase ref)

and here's the error message

com.tns.NativeScriptException: 
Calling js method onClick failed

Error: com.firebase.client.FirebaseException: Failed to parse node with class class com.tns.gen.com.firebase.client.Firebase_CompletionListener_fservice_firebase_l161_c72__
    com.firebase.client.snapshot.NodeUtilities.NodeFromJSON(NodeUtilities.java:84)
    com.firebase.client.snapshot.NodeUtilities.NodeFromJSON(NodeUtilities.java:12)
    com.firebase.client.snapshot.PriorityUtilities.parsePriority(PriorityUtilities.java:29)
    com.firebase.client.Firebase.setValue(Firebase.java:268)   

Is the android method override has limitation on parameters?

Thanks

@slavchev
Copy link

@x4080

We don't support extend syntax for Java interfaces. Use new instead as follows (code never tested)

        var complete = new com.firebase.client.Firebase.CompletionListener({
            onComplete: function (err, firebase) {
                console.log('complete');
            }
        });

        ref.child(url).setValue(object,new complete);

@x4080
Copy link

x4080 commented Mar 12, 2016

Ill try.. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants