4
This "resource" is just syntax sugar modifying the resolution scope including the object passed in the with
.
Although it can save a little typing, the use of this feature can cause confusion in reading the code when there are ambiguities, so he is discouraged.
There is no direct equivalent in Java, but you can find an equivalent depending on your goal.
Encapsulate the call to the object in the class itself
For example, let’s think of an equivalent code:
class ClassePrincipal {
Document document;
void metodo1() {
Context context = document.querySelector("body");
...
}
}
If you want to encapsulate the call without accessing the object document
directly, can do something like this:
class ClassePrincipal {
Document document;
void metodo1() {
Element context = querySelector("body");
...
}
Element querySelector(String selector) {
return document.querySelector(selector);
}
}
Although with one more method, our main method now no longer needs to access the attribute.
Well, for such a simple example it seems ridiculous, but if there are too many calls this encapsulation makes it easier to maintain the code. For example:
class ClassePrincipal {
Document document;
void metodo1() {
Element context = querySelector("body");
...
Element botao = querySelector("#botao");
...
Element menu = querySelector("#menu");
...
Element tabela = querySelector("table");
...
}
Element querySelector(String selector) {
return document.querySelector(selector);
}
}
This example is especially good if you for some reason want to avoid directly dealing with some API while avoiding too coupling your code.
An interesting case that has already occurred to me was to encapsulate the click
of Selenium because in some circumstances it did not find the element, so it was possible to change the implementation to use an alternative click technique.
Of course this does not work if you need to call several different methods of the object in question, so it is not a substitute one for one with the with
, but can help in this particular scenario.
Static import
For static calls, which do not depend on a specific instance of an object, Java also offers the import static
. Example:
class BibliotecaMatematica {
public static BigDecimal calcularJurosComposto(BigDecimal valorPresente, BigDecimal taxaDeJuros, int periodos) {
...
}
public static BigDecimal calcularJurosSimples(BigDecimal valorPresente, BigDecimal taxaDeJuros, int periodos) {
...
}
}
The normal mode of use would be:
class Calculadora {
void calcular() {
BigDecimal v1 = BibliotecaMatematica.calcularJurosComposto(...);
BigDecimal v2 = BibliotecaMatematica.calcularJurosSimples(...);
}
}
But we could create shortcuts like this:
import static BibliotecaMatematica.*;
class Calculadora {
void calcular() {
BigDecimal v1 = calcularJurosComposto(...);
BigDecimal v2 = calcularJurosSimples(...);
}
}
It is as if the static methods of the first class became part of the second class.
Initialization of objects
In Visual Basic or Delphi I’ve seen many people use the with
to initialize objects or log structures. By example:
With theWindow
With .InfoLabel
.Content = "This is a message."
.Foreground = Brushes.DarkSeaGreen
.Background = Brushes.LightYellow
End With
.Title = "The Form Title"
.Show()
End With
In Java this is usually not necessary because we prefer patterns like Builder or Factory method or simply use of constructors. Example:
public class HtmlElement {
private String tagName;
private Map<String,String> attributes;
private HtmlElement(String tagName, Map<String,String> attributes) {
this.tagName = tagName;
this.attributes = attributes;
}
public static HtmlElement of(String tagName, Map<String, String> attributes) {
return new HtmlElement(tagName, attributes);
}
}
So the client code goes like this:
HtmlElement table = HtmlElement.of("table", meusAttributos);
Builder Pattern and Fluent interfaces
Another alternative to boot is to use the Builder standard with chaining methods and fluent interfaces. I will not put the implementation here, but you can see this in more detail in my article.
The code to initialize an object would look like this:
new Pedido()
.para("José")
.com(1, "Motocicleta")
.com(2, "Capacete")
.fechar();
This is pretty cool to avoid confusion when there are too many parameters.
But what about the code Boilerplate?
Implementing the above standards requires a lot of code. Java is known to need a lot of code to do simple things.
An alternative is to adopt the project Lombok. See the code below:
@Data(staticConstructor="of")
public static class Exercise<T> {
private final String name;
private final T value;
}
The annotation @Data
would generate all the necessary code:
public static class Exercise<T> {
private final String name;
private final T value;
private Exercise(String name, T value) {
this.name = name;
this.value = value;
}
public static <T> Exercise<T> of(String name, T value) {
return new Exercise<T>(name, value);
}
public String getName() {
return this.name;
}
public T getValue() {
return this.value;
}
@Override public String toString() {
return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")";
}
protected boolean canEqual(Object other) {
return other instanceof Exercise;
}
@Override public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Exercise)) return false;
Exercise<?> other = (Exercise<?>) o;
if (!other.canEqual((Object)this)) return false;
if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false;
if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false;
return true;
}
@Override public int hashCode() {
final int PRIME = 59;
int result = 1;
result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());
return result;
}
}
Vc wants to print data at runtime?
– Emir Marques
Hey, no, that’s not it. I posted this photo together up there to demonstrate how it works in Js, I just want to know if anyone knows something similar in Java.
– Ilario Junior
It could detail a little more its operation?
– Emir Marques
Perhaps this is feasible to implement in java using black spells and heavy malignant sorcery such as bytecode manipulation, compiler-plugged annotation processing, and direct access to memory with
sun.misc.Unsafe
. None of these options are highly recommended and they are all only for the great Jedi masters who have become the dark side of the force. But either way, it should be possible.– Victor Stafusa