I'd like to have a Kotlin extension function for string that is accessible only in inheritors of MyParent class (protected function). MyParent class is written in java and cannot be converted to Kotlin. Is it possble to define a method in java code that can be used as extension function in Kotlin code?
I think I expect some kind of proper signature, or some magic #ThisIsExtenstionFunction annotation.
Actually, you can. Non out of box, but it is possible ;)
Let's consider this example.
First, create a class MyParent in Java
public class MyParent {
}
And, define extension method in this interface:
interface MyParentExt {
fun String.ext(importantParam: Int)
}
So, let MyParent implement this interface.
public class MyParent implements MyParentExt {
#NonNull
#Override
public String ext(#NonNull String $receiver, int importantParam) {
// do cool stuff
return $receiver;
}
// For testing let's add other public method:
public String ext(int importantParam) {
return "Kotlin > Java";
}
}
So, let's check what we can do in childs:
// Java child:
public class MyJavaChild extends MyParent {
MyJavaChild() {
"Java xD".ext(0); // Invalid! There is no such a method!
ext("Java xD", 0); // Valid call for extension function
ext(0); // Just Valid ;)
}
}
// Kotlin class:
class MyGreatKotlinChild : MyParent() {
init {
"Kotlin is cool".ext(0) // Valid extension function!
ext("Kotlin is cool", 0) // Invalid call. There is no method with such a signature!
ext(0) // Valid.
}
}
So, we can access our extension method in both, Java and Kotlin using lang-specified notation.
As one of your requirements you wanted this method to be protected.
Unfortunately, visibility of interface methods is always public. So, you still should be able to call this function on a member.
But... Let's check how does it actually works ;)
// Java
public class Test {
public static void main(String[] args) {
MyChild child = new MyChild();
// Both methods are valid
child.ext("Java...", 0);
child.ext(0);
}
}
// Kotlin
fun main() {
child.ext(0) // Normal function, valid call.
child.ext("It actually works...", 0) // Hah, no way ;)
// Just to be sure:
"String".ext(0) // Nope, this ext method is visible for only class scope.
}
Also, your parent class just can extend ParentOfMyParent class where you would define your extension methods:
// Kotlin
abstract class ParentOfMyParent {
protected abstract fun String.ext()
}
// Java
public class Parent extends ParentOfMyParent {
#Override
protected void ext(#NotNull String $receiver) {
}
}
// Kotlin-child
class Child : Parent() {
init {
"".ext()
}
}
// Java-child
public class ChildJava extends Parent {
ChildJava() {
ext("");
}
}
This way method has a wantned visibility.
There is no such annotation.
However, the compiler emits kotlin metadata annotations that might contain this information, but j would not recommend trying to trick the compiler into thinking some class is kotlin source rather than java source.
More info: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-metadata/index.html
Related
I do have a service which needs to handle two types of meal.
#Service
class MealService {
private final List<MealStrategy> strategies;
MealService(…) {
this.strategies = strategies;
}
void handle() {
var foo = …;
var bar = …;
strategies.forEach(s -> s.remove(foo, bar));
}
}
There are two strategies, ‘BurgerStrategy’ and ‘PastaStrategy’. Both implements Strategy interface with one method called remove which takes two parameters.
BurgerStrategy class retrieves meals of enum type burger from the database and iterate over them and perform some operations. Similar stuff does the PastaStrategy.
The question is, does it make sense to call it Strategy and implement it this way or not?
Also, how to handle duplications of the code in those two services, let’s say both share the same private methods. Does it make sense to create a Helper class or something?
does it make sense to call it Strategy and implement it this way or not
I think these classes ‘BurgerStrategy’ and ‘PastaStrategy’ have common behaviour. Strategy pattern is used when you want to inject one strategy and use it. However, you are iterating through all behaviors. You did not set behaviour by getting one strategy and stick with it. So, in my honour opinion, I think it is better to avoid Strategy word here.
So strategy pattern would look like this. I am sorry, I am not Java guy. Let me show via C#. But I've provided comments of how code could look in Java.
This is our abstraction of strategy:
public interface ISoundBehaviour
{
void Make();
}
and its concrete implementation:
public class DogSound : ISoundBehaviour // implements in Java
{
public void Make()
{
Console.WriteLine("Woof");
}
}
public class CatSound : ISoundBehaviour
{
public void Make()
{
Console.WriteLine("Meow");
}
}
And then we stick with one behaviour that can also be replaced:
public class Dog
{
ISoundBehaviour _soundBehaviour;
public Dog(ISoundBehaviour soundBehaviour)
{
_soundBehaviour = soundBehaviour;
}
public void Bark()
{
_soundBehaviour.Make();
}
public void SetAnotherSound(ISoundBehaviour anotherSoundBehaviour)
{
_soundBehaviour = anotherSoundBehaviour;
}
}
how to handle duplications of the code in those two services, let’s say both share the same private methods.
You can create one base, abstract class. So basic idea is to put common logic into some base common class. Then we should create abstract method in abstract class. Why? By doing this, subclasses will have particular logic for concrete case. Let me show an example.
An abstract class which has common behaviour:
public abstract class BaseMeal
{
// I am not Java guy, but if I am not mistaken, in Java,
// if you do not want method to be overriden, you shoud use `final` keyword
public void CommonBehaviourHere()
{
// put here code that can be shared among subclasses to avoid code duplication
}
public abstract void UnCommonBehaviourShouldBeImplementedBySubclass();
}
And its concrete implementations:
public class BurgerSubclass : BaseMeal // extends in Java
{
public override void UnCommonBehaviourShouldBeImplementedBySubclass()
{
throw new NotImplementedException();
}
}
public class PastaSubclass : BaseMeal // extends in Java
{
public override void UnCommonBehaviourShouldBeImplementedBySubclass()
{
throw new NotImplementedException();
}
}
public boolean sendRequest(final Object... params) {
if (!super.sendRequest(params)) {
return false;
}
...
// Some Log code or tracing code here
...
}
Why not implement a new method to call sendRequest rather than overwrite?
public boolean Send(final Object... params){
if (!super.sendRequest(params)) {
return false;
}
...
// Some Log code or tracing code here
...
}
Do you want your class with the override to be able to be used in the same way as members of the original class? i.e.:
...
class MyClass extends TheirClass {
#Override
void doIt() {
super.doIt();
// also do my stuff
}
}
...
// the doSomething function is part of the library where TheirClass lives.
// I can pass instances of MyClass to it, and doIt will be called, because MyClass IS-A TheirClass
theirFunction.doSomething(new MyClass(...));
...
But perhaps you just want to use the functionality of doIt, but don't need to use and code which expects a TheirClass.
In that case it is probably better to use composition rather than inheritance:
class MyClass {
private final TheirClass theirClass;
public MyClass(TheirClass theirClass) {
this.theirClass = theirClass;
}
public void doMyStuff() {
theirClass.doIt();
// and do some other things
}
}
This is better than inheritance with a new method name, because then you would have two methods on the class which do about the same thing (except the original doIt doesn't do your stuff), and it may not be clear which should be called.
Even inheritance where you override the method may have problems. We don't know what code in TheirClass calls doIt, so perhaps the code we've added will be called when we don't expect it to be.
Overall, composition should be preferred to inheritance whenever possible.
I'm trying to achieve the following:
I have a parent class, with some logic. In the child class, I "redefine" constants/properties. Is there any way to make the child properties accessible by methods defined in the parent class? Or to be more specific - is there any way to force the "out" method to write extended rather than base in the following example?
public class BaseTest {
public static final String x = "base";
public void out() {
System.out.println(x);
}
}
public class ExtendedTest extends BaseTest{
public static final String x = "extended";
}
public class Main {
public static void main(String[] args) {
BaseTest base = new BaseTest();
ExtendedTest extended = new ExtendedTest();
base.out(); // base (as expected)
extended.out(); // base (extended expected)
System.out.println(extended.x); // extended (as expected)
}
}
I come mainly from the world of PHP, where this approach works just fine. Dunno if I'm missing something or if the very design of Java does not allow this.
Thank you.
Note: This is not important whether the property is static or not. I just wanted to be able to override a property of any kind in a child class (just like I can override a method) which, on basis of the answers I've received so far, doesn't seem to be possible in Java. In PHP it is absolutely possible and that was why I asked the question.
static fields are not subject to inheritance. The x in the body of the out() method refers to BaseTest.x. Since you are not overriding out(), the body of the out() method still prints the value of BaseTest.x.
Static members are resolved at compile-time, and adding an ExtendedTest.x does not affect the also-existing BaseTest.x, which is what the BaseTest#out() method is linked to.
To accomplish what you're wanting, you need an overridden method:
public class BaseTest {
public String x() {
return "base";
}
public final void out() {
System.out.println(x());
}
}
public class ExtendedTest extends BaseTest {
#Override
public String x() {
return "extended";
}
}
This pattern is commonly used with an abstract method in the base class or interface to require the subclass to define an attribute such as a name or a key.
I facing a real hard problem in my code snippet.
I want to learn how to use Interface in Java the correct way.
So for this I have my Application-Class...
package inversionUsage;
public class Application {
public static void main(String [] args) {
String standard = "Standard version!";
if (FeatureDecisions.checkEnabledFeatures("new-feature1")) {
System.out.println("Implement new feature...");
}else {
System.out.println(standard);
}
}
}
Then I made a Interface...
package inversionUsage;
public interface AppConfiguration {
boolean isEnabled(String searchFeature);
}
I want to use the Interface in another class:
package inversionUsage;
import java.util.Arrays;
public class FeatureDecisions implements AppConfiguration{
public String [] enabledFeatures;
public String [] _implNewFeature = fetchFeatureTogglesFromSomehere();
public static boolean checkEnabledFeatures(String searchFeature) {
return isEnabled(searchFeature);
}
#Override
public boolean isEnabled(String searchFeature) {
if (Arrays.asList(_implNewFeature).contains(searchFeature)) {
return true;
}else {
return false;
}
}
private String [] fetchFeatureTogglesFromSomehere() {
// TODO get the CONFIG from somewhere
enabledFeatures = new String [2];
enabledFeatures[0] = "new-feature1";
enabledFeatures[1] = "new-feature2";
return enabledFeatures;
}
}
So the workflow is:
1. I start the Application
2. Main method checks the enabled features via FeatureDecisions.java
3. In Feature Decisions i implemented the Interface
I getting the error:
Cannot make a static reference to the non-static method isEnabled(String) from the type FeatureDecisions
May Someone can help me out?
The only way to use an instance method is to have an instance on which to call it. Your checkEnabledFeatures is static, so it doesn't receive an instance you can use (as this). To use an instance method, it would need to create an instance. But obviously that's not what you want here.
Java's interface construct is for defining the interface that instances implement. Java doesn't have the concept of a "static interface" that a class must implement. On the rare occasions when that's needed, it's usually implemented using reflection (perhaps with a class-level annotation to indicate that the class has the necessary feature).
You would have to instantiate the FeatureDecisions class.
public static boolean checkEnabledFeatures(String searchFeature) {
return new FeatureDecisions().isEnabled(searchFeature);
}
or make all members static.
Additional info: There are frameworks like togglz that do this for you.
There's no way to do that. The closest can get is to use the singleton pattern (though lots of people - myself included - would discourage it).
public enum FeatureDecisions implements AppConfiguration
{
INSTANCE;
public String [] enabledFeatures;
public String [] _implNewFeature = fetchFeatureTogglesFromSomehere();
public boolean checkEnabledFeatures(String searchFeature) {
return isEnabled(searchFeature);
}
#Override
public boolean isEnabled(String searchFeature) {
//...
}
}
Your call would then change from:
FeatureDecisions.checkEnabledFeatures(...)
to
FeatureDecisions.INSTANCE.checkEnabledFeatures(...)
It's also worth noting that checkEnabledFeatures doesn't actually do anything besides defer to isEnabled. You could scrap the former and just call the latter directly.
Small preamble. I was good java developer on 1.4 jdk. After it I have switched to another platforms, but here I come with problem so question is strongly about jdk 1.6 (or higher :) ). I have 3 coupled class, the nature of coupling concerned with native methods. Bellow is example of this 3 class
public interface A
{
public void method();
}
final class AOperations
{
static native method(. . .);
}
public class AImpl implements A
{
#Override
public void method(){
AOperations.method( . . . );
}
}
So there is interface A, that is implemented in native way by AOperations, and AImpl just delegates method call to native methods.
These relations are auto-generated. Everything ok, but I have stand before problem. Sometime interface like A need expose iterator capability. I can affect interface, but cannot change implementation (AImpl).
Saying in C# I could be able resolve problem by simple partial:
(C# sample)
partial class AImpl{
... //here comes auto generated code
}
partial class AImpl{
... //here comes MY implementation of
... //Iterator
}
So, has java analogue of partial or something like.
EDITED:
According to comment by #pgras I need some clarification. AImpl is not in vacuum, there is some factory (native implemented) that returns instance of AImpl, that is why creation of inheritance from AImpl, is not applicable.
EDITED 2:
May be it doesn't relate, but how it is done by JUnit 4:
public class SomeTest {
...
//there is no direct inheritance from Assert, but I can use follow:
assertTrue(1==1); //HOW DOES it works??
Java does not have support for partials or open classes. Other JVM languages do, but not Java. In your example, the simplest thing may unfortunately be to use delegation. You can have your AImpl take another object that fulfills an interface to these extension methods. The generated AImpl would then have generated methods such as iterator methods that it could delegate to the user created object you pass in.
How about that:
Compute.java = your class
Compute$.java = base class for partial classes. Reference a Compute object
Compute$Add.java = your partial class. Subclass Compute$.
Compute$Sub.java = your partial class. Subclass Compute$.
file Compute.java
public class Compute {
protected int a, b;
Compute$Add add;
Compute$Sub sub;
public Compute() {
add = new Compute$Add(this);
sub = new Compute$Sub(this);
}
public int[] doMaths() {
int radd = add.add();
int rsub = sub.sub();
return new int[] { radd, rsub };
}
}
file Compute$.java
public abstract class Compute$ {
protected Compute $that;
public Compute$(Compute c){
$that=c;
}
}
file Compute$Add.java
public class Compute$Add extends Compute$ {
public Compute$Add(Compute c) {
super(c);
// TODO Auto-generated constructor stub
}
public int add(){
return $that.a+$that.b;
}
}
file Compute$Sub.java
public class Compute$Sub extends Compute$ {
public Compute$Sub(Compute c) {
super(c);
}
public int sub() {
return $that.a - $that.b;
}
}
You could extend A (say interface B extends A) and extend AImpl and implement B (class BImpl extends AImpl implements B)...