Como programador Java mas entusiasta de novas linguagens, acabo por sentir falta de alguns recursos que facilitam muito o trabalho, ou que pelo menos para mim fazem mais sentido usar.
Posso começar com um estudo de caso simples: dada uma String retornar o número de palavras.
É assim mesmo, simples assim, inclusive muito fácil de implementar em qualquer linguagem, mas a questão não é essa, como desenvolvedor eu quero usar orientação a objetos no projeto.
Vamos a uma implementação tosca em Java:
String frase = "Uma frase de exemplo";
System.out.println(frase.trim().split("\\s+").length);
Deu. Mostra 4. Entretanto eu quero reutilizar esta funcionalidade então em componentizo, bem, mas como?
Posso usar outro estudo de caso para dramatizar mais a história: verificar se uma String está em branco, ou seja, semelhante ao vazio só que ignorando espaços.
A implementação é medíocre:
String texto = " ";
if (texto.trim().length() == 0) {
System.out.println("vazio");
}
Não obstante, como no primeiro caso, eu quero componentizar.
No Java, é clássico fazer uma classe utilitária, algo como TipoUtils, neste caso, StringUtils:
public class StringUtils {
public static int words(String str) {
return str.trim().split("\\s+").length;
}
public static boolean isBlank(String str) {
return str.trim().length() == 0;
}
}
E uso assim:
String texto = " ";
if (StringUtils.isBlank(texto)) {
System.out.println("vazio");
}
Ainda posso usar um recurso introduzido no Java 5, o import estático.
import static meu.framework.utils.StringUtils.*;
// algumas linhas abaixo
String texto = " ";
if (isBlank(texto)) {
System.out.println("vazio");
}
Qual o problema com esta implementação? É que ela soa totalmente procedural em contraste ao modelo OO escolhido, em outras palavras eu queria fazer isso:
String texto = " ";
// quero o próprio objeto me diga se está em branco
if (texto.isBlank()) {
System.out.println("vazio");
} else {
// quero que o próprio objeto me diga quantas palavras tem
System.out.println("Existem " + texto.words() + " palavra(s)");
}
Em Java, impossível. No Java a classe String é final, ou seja, não pode ser estendida.
Para constar, uma extensão da API base do Java já existe e é distribuída pelo projeto
commons do Apache e uma classe
StringUtils já existe para estender as funcionalidades relacionadas a Strings e é muito bem escrita.
Mas isso não me deixa contente por que outras linguagens lidam muito melhor com esta situação, dando melhor suporte para estender a API base.
Vamos ao mesmo exemplo usando C#. No C# é possível, de certo modo, estender qualquer classe, mesmo as finais (sealed em C#), usando somente a API pública da classe, que já é suficiente para realizar muitas proezas:
public static class StringUtils {
public static int Words(this string str) {
return Regex.Split(str.Trim(), "\\s+").Length;
}
public static bool IsBlank(this string str) {
return str.Trim().Length == 0;
}
}
Implementações de classes estáticas no C# permitem estender a funcionalidade qualquer classe. Na verdade é um açúcar sintático no qual ele passa o conteúdo da variável para o método estático, ainda sendo procedural, mas de melhor leitura e mais elegante que em Java. Eu posso chamá-lo assim:
string texto = " ";
if (texto.IsBlank()) {
Console.WriteLine("vazio");
} else {
Console.WriteLine("Existem " + texto.Words() + " palavra(s)");
}
Bem mais OO não acha?
Pode ficar ainda melhor em Ruby, onde as classes são abertas. Em outras palavras, é possível estender a funcionalidade até mesmo das classes básicas como String e FixNum (inteiros). Claro que esta liberdade deve ser usada com parcimônia, é bem mais fácil fazer caca, mas com responsabilidade dá para fazer isso:
class String
def words
self.split.length
end
def blank?
self.strip.length == 0
end
end
Então eu posso usar estes métodos assim:
texto = "uma frase"
print texto.words
print "vazio" if texto.blank?
Sinceramente, sinto falta dessa flexibilidade em Java.
Acho exagerado a recomendação do Pragmatic Programmers de que todo programador deveria aprender uma linguagem por ano, por outro lado entendo o motivo que é propiciar novas visões, pontos de vista, ser mais crítico ao seu código, saber que há alternativas para fazer, melhor ou pior, aquilo que tu já faz todo o dia.