I have an application that contains a generic interface:
public interface IMyInterface<T> {
public int calcStuff(T input);
}
I can clearly implement this in Java:
public class Implementor implements IMyInterface<FooObject>{
public int calcStuff(FooObject input){ ... }
}
I have found a tutorial on implementing Java non-generic interfaces in Rhino and can verify that it works in my context.
As far as I understand Javascript has no generics due to the dynamic type system and other factors, so Rhino does not provide such a concession in its JS parser. Any attempts to do research lead me to a plethora of results about Rhino mocks generic interfaces but not Rhino JS generic interface implementation.
From a Javascript point of few, there are no generics, no interfaces, not even classes. In Javascript you have Objects with functions that may be created from prototypes.
To "implement" a Java interface in Javascript only means, to provide some Javascript object, that has the same function names as the interfaces method names, and these functions have the same number of arguments as the corresponding interface methods.
So to implement the generic example interface you provided, you can write something like this:
myGenericInterfaceImpl = new Object();
// Generic type is supposed to be <String> int calcStuff(String)
myGenericInterfaceImpl.calcStuff = function(input) {
println("--- calcStuff called ---");
println("input" + input);
println("typeof(input):" + typeof(input));
// do something with the String input
println(input.charAt(0));
return input.length();
}
Here it is assumed, that the intended generic class is of type String.
Now lets say, you have a Java class, that accepts this interface with a generic String type:
public static class MyClass {
public static void callMyInterface(IMyInterface<String> myInterface){
System.out.println(myInterface.calcStuff("some Input"));
}
}
You can then call this method from Javascript like so:
// do some Java thing with the generic String type interface
Packages.myPackage.MyClass.callMyInterface(new Packages.myPackage.IMyInterface(myInterfaceImpl)));
Some background information on the topic
If you are interested in what goes on behind the scenes in Rhino, when implementing a Java interface in Javascript, I recommend to have a look at the following Rhino classes:
https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/jdk13/VMBridge_jdk13.java
https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/InterfaceAdapter.java
Essentially the static method InterfaceAdapter#create() will call VMBridge#newInterfaceProxy(), which returns a Java Proxy for the interface, that uses an instance of InterfaceAdapter to handle method invocations on your interface. This proxy will map any Java method call on the interface to the corresponding Javascript functions.
**
* Make glue object implementing interface cl that will
* call the supplied JS function when called.
* Only interfaces were all methods have the same signature is supported.
*
* #return The glue object or null if <tt>cl</tt> is not interface or
* has methods with different signatures.
*/
static Object create(Context cx, Class<?> cl, ScriptableObject object)
When I first worked with generic interfaces in both Java and Javascript, it also helped me quite a lot to understand what is going on, by step debugging my invocations on the created Rhino proxies (but you will of course need the Rhino source to do that, and setting it up can be a little cumbersome).
Also note, that the default Rhino implementation used by the Java Scripting API does not allow to implement multiple Java interfaces or to extend Java classes. From the Java Scripting Programmer's Guide:
Rhino's JavaAdapter has been overridden. JavaAdapter is the feature by
which Java class can be extended by JavaScript and Java interfaces may
be implemented by JavaScript. We have replaced Rhino's JavaAdapter
with our own implementation of JavaAdapter. In our implementation,
only single Java interface may be implemented by a JavaScript object.
So if you need these features, you will need to install the original Rhino implementation anyway (which makes it easier to set up the source code).
Related
I'm using Dictionary class to localize my application, since I want my texts to be files outside of the application, so I can change them without the need to compile the app again.
To be able to get the strings, I created class StringIdentifiers, that had all the methods like:
public String minute(){
return getString("minute");
}
The method getString() basically just used a Dictionary to get the string from a JSON included into the page.
I then created subclass called Language, where I had some more logic (checking what language to use etc.). It all worked flawlessly, I used the Language subclass to access the Strings. Even in UIBinder.
Since there are more and more texts now, I decided to split these methods into separate classes. But since in Java I cannot do multiple inheritance, I decided to do it via interfaces. So instead of StringIdentifiers I created interfaces like: LoginTexts, MenuTexts, EventLogTexts etc. In these interfaces I specified default methods to get the appropriate strings. The Language class implements all the interfaces and also the getString() method.
Now it all works fine, I get instance of the Language class, I can use methods from the interfaces in the code, no errors.
BUT when it comes to UI binder, it doesn't show errors in editor, but at compilation it tells:
[ERROR] Could not find no-arg method named minute in type
com.company.project.client.locale.Language
Does this mean, that UI binder is not able to see inherited default method from the interfaces? Really? I mean in the Java code, it is working normally.
Im experiencing the same issue, however, after searching I discovered this clever work-around written by Jos31fr: https://github.com/gwtproject/gwt/issues/9629
Define the interface assuming that GWT supports default methods.
In the class implementing the interface, redefine the default method as a call to the super-class.
import com.google.gwt.user.client.ui.TextBox;
public class TestTextBox extends TextBox implements TestInterface {
public void setFoo(String bar) {
TestInterface.super.setFoo(bar);
}
}
I am looking for a java equivalent to the C# extension methods feature. Now I have been reading about Java 8's default methods, but as far as I can see, I can only add these to interfaces...
...is there any language feature that will allow me to write an extension method for a final class that doesn't implement an interface? (I'd rather not have to wrap it...)
Java doesn't have extension methods. Default methods are not extension methods. Let's look at each feature.
Default methods
Both Java and C# support this feature
Problems solved:
Many objects may implement the same interface and all of them may use the same implementation for a method. A base class could solve this issue but only if the interface implementors don't already have a base class as neither java nor C# support multiple inheritance.
An API would like to add a method to an interface without breaking the API consumers. Adding a method with a default implementation solves this.
Java's or C#'s default methods are a feature to add a default implementation to an interface. So objects that extend an interface don't have to implement the method, they could just use the default method.
interface IA { default public int AddOne(int i) { return i + 1; } }
Any object that implements IA doesn't have to implement AddOne because there is a default method that would be used.
public class MyClass implements IA { /* No AddOne implementation needed */ }
C# now has this feature in C# 8 (or .Net 5)
C#'s Extension Method
Problems solved:
Ability to add methods to sealed classes.
Ability to add methods to classes from third-party libraries without forcing inheritance.
Ability to add methods to model classes in environments where methods in model classes are not allowed for convention reasons.
The ability for IntelliSense to present these methods to you.
Example: The type string is a sealed class in C#. You cannot inherit from string as it is sealed. But you can add methods you can call from a string.
var a = "mystring";
a.MyExtensionMethed()
Java lacks this feature and would be greatly improved by adding this feature.
Conclusion
There is nothing even similar about Java's default methods and C#'s extension method features. They are completely different and solve completely different problems.
C# extension methods are static and use-site, whereas Java's default methods are virtual and declaration-site.
What I believe you are hoping for is the ability to "monkey-patch" a method into a class you do not control, but Java does not give you that (by design; it was considered and rejected.)
Another benefit of default methods over the C# approach is that they are reflectively discoverable, and in fact from the outside, don't look any different from "regular" interface methods.
One advantage of C#'s extension methods over Java's default methods is that with C#'s reified generics, extension methods are injected into types, not classes, so you can inject a sum() method into List<int>.
Above all, the main philosophical difference between Java's default methods and C#'s extension methods is that C# lets you inject methods into types you do not control (which is surely convenient for developers), whereas Java's extension methods are a first-class part of the API in which they appear (they are declared in the interface, they are reflectively discoverable, etc.) This reflects several design principles; library developers should be able to maintain control of their APIs, and library use should be transparent -- calling method x() on type Y should mean the same thing everywhere.
C# extension methods are just syntactic sugar for static methods that take the extended type as first argument. Java default methods are something completely different. To mimic C# extension methods, just write usual static methods. You will not have the syntatic sugar, however; Java does not have this feature.
Java default methods are real virtual methods. For example, they can be overridden. Consider a class X inheriting from an interface I that declares a default foo() method. If X or any of its super classes declares no own foo() method, then X will get the foo() implementation of I. Now, a subclass Y of X can override X.foo() like a usual method. Thus, default methods are not only syntactic sugar. They are real extensions of the method overriding and inheritance mechanism that cannot be mimicked by other language features.
Default methods even require special VM support, so they are not even a compiler only feature: During class loading, the hierarchy of a class has to be checked to determine which default methods it will inherit. Thus, this decision is made at runtime, not at compile time. The cool thing about it is that you do not have to recompile a class when an interface it inherits gets a new default method: The VM will, at class load time, assign that new method to it.
It is possible to have extension methods with some tricks.
You may give a try to Lombok or XTend. Although extension methods don't come with the out of the box Java implementation, both Lombok and XTend offers a fully working solution.
Lombok is a simple standalone code processing framework, which makes most of the criticized Java specific hassle less painful, including extension methods:
https://projectlombok.org/features/experimental/ExtensionMethod.html
Xtend http://www.eclipse.org/xtend/ goes a few lightyears forward, and implements a language which is a combination of the best parts of modern languages such as Scala on top of Java and Java type system. This allows implementing some classes in Xtend and others in Java within the same project. The Xtend code complies to valid Java code, so no JVM magic happens under the hood. On the other hand, it is a little too much if you have only extension methods missing.
JPropel https://github.com/nicholas22/jpropel-light implements LINQ style extension methods in Java using Lombok. It may worth of a peek :)
Why do Java introduces some interface which has no methods defined in it? For example Cloneable, Serializable, Type and many more.
Second thing : In Class.class package there is one method defined registerNatives() without body and is called from static block but Class.class is not abstract but is final. Why so?
and Why Java need some method without body to be called from static block.?
Why do Java introduces some interface which has no methods defined in it?
This are called Tagged or Marker interface. These are not used for any use or operation. These methods are used to tag or marking a class. So that you can determine whether someclass is a child of those classes.
about the second question
If you look closely you can see the declaration is
private static native void registerNatives();
So registerNatives is a native methods.
So what is native methods. If you see this so question
The method is implemented in "native" code. That is, code that does
not run in the JVM. It's typically written in C or C++.
Native methods are usually used to interface with system calls or
libraries written in other programming languages.
So these methods are loaded from native codes. So you don't need to declare the body of the methods but still they are not abstract as they have their implementation from native codes.
Marker interface is used as a tag to inform a message to the java compiler so that it can add special behavior to the class implementing it. Java marker interface has no members in it.
The purpose of Marker interfaces is to force some kind of functionality in the classes by providing some functionality to a class if it implements the marker interface.
Read Java Marker Interface also see What is the use of marker interfaces in Java?
For the first one you are actually asking for a Marker Interface. Marker Interfaces are by design not supposed to add anything to behavior but support only polymorphic transformation of the object. e.g. Serializable makes an object capable of streaming across JVM boundaries. Marker interfaces follow the 'universal type substitution' philosophy.
For second one, you are actually asking for JNI. Java doesnot implement all its code in Java form. I mean in classes and code that follow Java syntax. Some time or the other you need to drill down to the native platform API to implement something for that API. e.g. sockets and TCP communication. It is this feature of Java that actually makes it platform independent. The JVM runtime is platform dependent as it uses platform based native methods and dll or .so libraries to implement and integrate with the platform. We as programmers call the high level Java SDK API calls.
One of the "clean" features of the Java programming language is that it mandates a separation between interfaces (pure behavior) and classes (state and behavior). Interfaces are used in Java to specify the behavior of derived classes.
Often you will come across interfaces in Java that have no behavior. In other words, they are just empty interface definitions. These are known as marker interfaces. Some examples of marker interfaces in the Java API include:
java.lang.Cloneable
java.io.Serializable
java.util.EventListener
Marker interfaces are also called "tag" interfaces since they tag all the derived classes into a category based on their purpose. For example, all classes that implement the Cloneable interface can be cloned (i.e., the clone() method can be called on them). The Java compiler checks to make sure that if the clone() method is called on a class and the class implements the Cloneable interface. For example, consider the following call to the clone() method on an object o:
SomeObject o = new SomeObject();
SomeObject ref = (SomeObject)(o.clone());
If the class SomeObject does not implement the interface Cloneable (and Cloneable is not implemented by any of the superclasses that SomeObject inherits from), the compiler will mark this line as an error. This is because the clone() method may only be called by objects of type "Cloneable." Hence, even though Cloneable is an empty interface, it serves an important purpose.
registerNatives()
native method are implemented in JVM itself.
What does the registerNatives() method do?
Why Java need some method without body to be called from static block.?
This is called from static block because we need to call this method when classes are loaded and not when it's instance is created.
With SWIG am able to create simple bindings for my C++ code.
My question here is for multiple inheritance.
Our C++ codebase has a iClass as base class, which acts as interface. Also we have classes that are derived from two classes, one of which is this interface class.
Now my question is can we use SWIG to create bindings for such a codebase, assuming that we can put our class iClass as an Interface in Java.
It is still multiple inheritance but a very specific case of it and is analogous with interface concept of java.
The case with SWIG is that it indeed will only extend the first base class you list (in the code example below that would be I1) and omit the rest. Interestingly, the C++ compiled code WILL include all the base methods, they are just not available to the Java JNI wrapper.
Multiple inheritance is another paradigm than interfacing, making it hard to cast / interpret an Object in Java as belonging to a particular interface.
What you can do though - which does feel a tad fugly - is to add a compiler directive to the header file of the class which is inheriting from multiple classes. Like so:
class Foo : public I1, I2
{
public:
Foo();
~Foo();
#ifdef SWIG
void aI2Method();
double aI2Property;
#endif
protected:
void bar();
}
When compiling with SWIG, property SWIG is defined. As such the method "aI2Method" and public property "aI2Property" (which for the sake of argument, we assume are defined in base class I2) are used by SWIG and defined in the JNI wrapper for this class "Foo". Just add the public methods / properties in between the conditional directive.
In Java you can then invoke "aI2Method" on Foo or get/set the public "aI2Property"-property, and the native compiled code will invoke these on the I2 base class. Note that this means you don't need to add the same directive including the definitions or function bodies of these methods in the .cpp file of "Foo", as placing it in the header file will suffice. This way, at least the .cpp files remain clean.
I am trying to create a Java wrapper for my C++ library using SWIG.
In order to get all the features I need within a Java programming environment, I need directors.
More specifically, I need Java users to be able to inherit from my C++ classes and implement certain methods.
In particular, one of the method that needs to be implemented is some sort of clone() method.
In C++, the user implementation provides an object pointer Base*. This pointer is then managed by the library itself.
Base* Derived::clone() {
return new Derived(*this);
}
The problem I have with the Java wrapper is that the Java proxy class for Base acquires the management of the corresponding C++ director class SwigDirector_Base, by default.
This is certainly suitable in the general case, but not in this particular user-defined clone() function.
My personal constraint is that the Java wrapper for my C++ library uses no Java-specific code, so the user implementation should look like:
class Derived {
...
Base clone() {
return new Derived(this);
}
}
So far, to make it work and avoid garbage collection of the copied Java instance, I have used the trick mentioned in http://www.swig.org/Doc2.0/SWIGDocumentation.html#CSharp_memory_management_member_variables.
And to make sure that the Java Derived class never deletes the corresponding C++ director class SwigDirector_Base, I have used %typemap(directorout) to set the value of the Java cMemOwn flag of the copied instance from the C++ wrapper code, that is in method SwigDirector_Base::clone().
I am not so happy with this solution as it applies to all methods returning a pointer to the Base class, whether it is a copy method or not...
Any idea on how to do this on a function-specific way? Or in any other way?