Reputation: 5133
Let's say I have a Java class called A
and an interface called I
. The A
class implements the interface I
. Interface I
has the following method definition byte[] x(String in)
. The interface I
is also implemented by other classes like B
, C
, D
and so on.
Now let's say I want to send an extra argument for the implementation of x
method from A
. Let's say I want to have a new definition, something like byte[] x(String in, OutputStream os)
.
Is there any way to pass that OutputStream os
in the x
method without affecting other implementations? The problem is that if I make a change in I
, I have to make this change in all implementations which is not OK. If I choose to change the x
method signature, I will have to change it in all the methods and pass the second argument everywhere in the code.
That OutputStream
must come from a @Controller
and this OutputStream
must be a different stream (a stream per request).
My implementations are @Component
used in @Service
.
Do you have any suggestions on how to pass that stream only to my A
class for x
?
The actual purpose of x
is to write the returned bites to generate a file. Sending the OutputStream
will somehow determine the return type to become void
because data will be sent directly to the stream.
Upvotes: 2
Views: 2906
Reputation: 5820
Yes, you can do it in Java 8 using default methods in interfaces:
public interface I {
byte[] x(String in);
default byte[] x(String in, OutputStream os) {
return x(in);
}
}
So, all classes which implement I contain implementation of old method x(String in) and inherit default implementation of new method x(String in, OutputStream os) from interface. You can override and reimplement the new method only in one class where you need a specific behavior for this method.
An update for author's explanation of his problem in comments (A
generates big byte[] object, so, only in this A
class we want to implement optimization by writing directly to OutputStream):
public interface I {
byte[] x(String in);
default void x(String in, OutputStream os) {
try {
os.write(x(in));
} catch (IOException e) {
//handle it
}
}
}
So, you call x(String in, OutputStream os) from your controller, in case of classes B
, C
, ... original implementation will be called and written to output stream, while for A we will call optimized version without creation of big intermediate objects. I changed return value of x(String in, OutputStream os)
, because in that case you have no need to produce byte[]
, you just write to output stream in implementations.
Upvotes: 5
Reputation: 2566
You can't change the definition of x in the interface without changing all classes that implement it. You can add x with the additional parameter as a separate method, since it will just be an overloaded version of x. However, you would not be able to call it when treating the instance of A as an I.
Upvotes: 0