Even if you can use lambda expressions in streams, you may not be able to take advantage of functional interfaces in your own functions. For such people, I would like to introduce how to apply a functional interface to a self-made function using a simple example.
It's common to copy the properties of one object to another. At that time, it is often the case that the condition of copying is set only when the value of the property is not null. And, as in this example, copies of various type properties are often lined up. There may be cases where you can copy and paste in this way, but I would like to devise a little. Let's create a common function for the following code to simplify the call. Note that getName () returns a String, and setName () sets a String. getFlag () returns a Boolean and setFlag () sets a Boolean.
if(objA.getName()!=null) {
objB.setName(objA.getName());
}
if(objA.getFlag()!=null) {
objB.setFlag(objA.getFlag());
}
I hope you can write it as follows. Let's see how it is achieved in java.
setIfNotNull(value,func) {
if(value!= null) {
func(value);
}
}
setIfNotNull(objA.getName(),objB.setName);
setIfNotNull(objA.getFlag(),objB.setFlag);
In the above pseudo code, func shows a method, but how should it be expressed in java? An interface is what indicates a method. Again, it may be possible with an interface.
public interface SetNameInterface {
void setName(String value);
}
public Class ObjB implements SetNameInterface{
void setName(String name);
}
public void setIfNotNull(String value,SetNameInterface obj) {
if(value!= null) {
obj.setName(value);
}
}
setIfNotNull(objA.getName(),objB);
It was possible to support setName (), but it is clear that it is not compatible with setFlag (). This method is intuitive, but it doesn't work.
Because we want to call setName () and setFlag () from setIfNotNull () with the common function name func. How about having an object with func as an interface for setName () and setFlag ()?
public Class ObjB {
public void setName(String name) {
System.out.println("OnjB.setName:"+name);
}
public void setFlag(Boolean flag) {
System.out.println("OnjB.setFlag:"+flag);
}
}
public interface FuncInterface<T> {
void func(T value);
}
public class ObjBSetName implements FuncInterface<String> {
ObjB obj;
public ObjBSetName(ObjB obj) {
this.obj = obj;
}
@Override
public void func(String value) {
obj.setName(value);
}
}
public class ObjBSetFlag implements FuncInterface<Boolean> {
ObjB obj;
public ObjBSetFlag(ObjB obj) {
this.obj = obj;
}
@Override
public void func(Boolean value) {
obj.setFlag(value);
}
}
public <T>void setIfNotNull(T value,FuncInterface<T> obj) {
if(value!= null) {
obj.func(value);
}
}
setIfNotNull(objA.getName(),new ObjBSetName(objB));
setIfNotNull(objA.getFlag(),new ObjBSetFlag(objB));
ObjBSetName and ObjBSetFlag both have func functions defined in the FuncInterface interface. When the func function is called, the original processing objB.setName () and objB.setFlag () are called. The FuncInterface interface declares the type of the parameter passed to the method as a generic type (T in this case). Correspondingly, setIfNotNull () also changes value and obj to use generic types.
I've achieved what I want to do with this, but it is redundant to prepare ObjBSetName and ObjBSetFlag. Let's use an anonymous class.
How to write an anonymous class
new parent class or interface name () { Anonymous class content (field and method definitions) };
Because it is
var objBSetName = new FuncInterface<String>() {
@Override
public void func(String value) {
objB.setName(value);
}
};
var objBSetFlag = new FuncInterface<Boolean>() {
@Override
public void func(Boolean value) {
objB.setFlag(value);
}
};
Write, The call is
setIfNotNull(objA.getName(),objBSetName);
setIfNotNull(objA.getFlag(),objBSetFlag);
It will be. Within the anonymous class, you can directly reference the object objB.
For interfaces with only one function defined, anonymous classes can be replaced with lambda expressions, so
FuncInterface<String> objBSetName = (v) -> objB.setName(v);
FuncInterface<Boolean> objBSetFlag = (v) -> objB.setFlag(v);
Can be rewritten as. The lambda expression does not have the notation func, but it implements the func defined in FuncInterface. It's hard to see that func disappears in lambda expressions, but you can understand it by comparing it with anonymous classes.
Omit more variables
setIfNotNull(objA.getName(),(v) -> objB.setName(v));
setIfNotNull(objA.getFlag(),(v) -> objB.setFlag(v));
Can be summarized as.
By the way, the declaration of the interface called FuncInterface is actually as a functional interface. Consumer already exists, so let's replace it with this one. (Before creating your own interface, it's a good idea to check if you can use the provided functional interface.)
public <T>void setIfNotNull(T value,Consumer<T> obj) {
if(value!= null) {
obj.accept(value);
}
}
In addition, since it has one argument, the call uses a method reference,
setIfNotNull(objA.getName(),objB::setName);
setIfNotNull(objA.getFlag(),objB::setFlag);
It will be. It was pretty neat.
This time, I explained with a small example, but you can see that "processing" can be passed to a function. I think. The declaration for that is the "functional interface". You may have already imagined that you could use it to achieve the "Strategy pattern". Please apply it to your program and reuse the program.
Recommended Posts