nav-title | title | description | position |
---|---|---|---|
Extending Classes And Interfaces |
Extending Classes And Interfaces |
NativeScript Android Runtime Extending Classes And Interfaces |
2 |
As part of the native Android development you often have to inherit from classes and/or implement interfaces. NativeScript supports these scenarios as well.
public class MyButton extends android.widget.Button {
public MyButton(Context context) {
super(context);
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
}
}
MyButton btn = new MyButton(context);
Here is how the above is done in NativeScript:
var constructorCalled = false;
var MyButton = android.widget.Button.extend({
//constructor
init: function() {
constructorCalled = true;
},
setEnabled: function(enabled) {
this.super.setEnable(enabled);
}
});
var btn = new MyButton(context);
//constructorCalled is true here
Note: In the above setEnabled function the
this
keyword points to the JavaScript object that proxies the extended native instance. Thethis.super
property provides access to the base class method implementation.
The next example shows how to implement an interface in Java and NativeScript. The main difference between inheriting classes and implementing interfaces in NativeScript is the use of the extend
keyword. Basically, you implement an interface by passing the implementation object to the interface constructor function. The syntax is identical to the Java Anonymous Classes.
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
button.setOnClickListener(new android.view.View.OnClickListener({
onClick: function() {
// Perform action on click
}
}));
Suppose you have the following interfaces in Java:
public interface Printer {
void print(String content);
void print(String content, int offset);
}
public interface Copier {
String copy(String content);
}
public interface Writer {
void write(Object[] arr);
void writeLine(Object[] arr)
}
Implementing the interfaces is as easy in Java as writing:
public class MyVersatileCopywriter implements Printer, Copier, Writer {
public void print(String content) { ... }
public void print(String content, int offset) { ... }
public String copy(String content) { ... }
public void write(Object[] arr) { ... }
public void writeLine(Object[] arr) { ... }
}
The same result can be achieved in NativeScript by extending(./how-extend-works.md) any valid object that inherits Java Object, and declaring an interfaces array in the implementation as shown below:
Using Javascript syntax - attach interfaces
array to implementation object of the extend call
var MyVersatileCopyWriter = java.lang.Object.extend({
interfaces: [com.a.b.Printer, com.a.b.Copier, com.a.b.Writer], /* the interfaces that will be inherited by the resulting class */
print: function() { ... }, /* implementing the 'print' methods from Printer */
copy: function() { ... }, /* implementing the 'copy' method from Copier */
write: function() { ... }, /* implementing the 'write' method from Writer */
writeLine: function() { ... }, /* implementing the 'writeLine' method from Writer */
toString: function() { ... } /* override `java.lang.Object's` `toString */
});
Using Typescript syntax - apply a decorator to the extended class (note @Interfaces([...]
))
@Interfaces([com.a.b.Printer, com.a.b.Copier, com.a.b.Writer]) /* the interfaces that will be inherited by the resulting MyVersatileCopyWriter class */
class MyVersatileCopyWriter extends java.lang.Object {
print() { ... }
copy() { ... }
write() { ... }
writeLine() { ... }
}
- Implementing two interfaces with the same method signature will generate just 1 method. It is the implementor's responsibility to define how the method will behave for both interfaces
- Implementing two interfaces with the same method name, parameter number, but different return type (
void a()
vsboolean a()
) will result in a compilation error
Java method overloads are handled by the developer by explicitly checking the
arguments
count of the invoked function
var MyVersatileCopyWriter = ...extend({
...
print: function() {
var content = "";
var offset = 0;
if(arguments.length == 2) {
offset = arguments[1];
}
content = arguments[0];
// do stuff
}
...
})
When implementing Java interfaces in NativeScript, it is necessary to provide implementation (declare the methods -
copy
,write
,writeLine
) for every method present in the interfaces, otherwise compilation will fail. If you do not want to fully implement an interface you need to declare empty functions. Functions with empty bodies are considered valid method implementations (print: function() {}
).
In addition to implementing interface methods, you can override methods of the extended class, and also declare your own methods that the new class should have.