vitorbtf:
Ultima duvida , sobre essas outras funcionalidades da plataforma .Net, elas são conceitos 'adicionais' de OO ou entendi errado ?
Não são exatamente conceitos da OO, mas facilidades da linguagem. Veja algumas delas:
Properties
Propriedades permitem eliminar a sintaxe incômoda dos gets e sets, sem eliminar sua funcionalidade. Por exemplo:
public class Fruta {
private string nome;
private double preco;
public string Nome {
get {
return nome;
}
set {
if (value == null)
throw new ArgumentException("O nome não pode ser nulo!");
value = value.trim();
if (value.length == 0)
throw new ArgumentException("O nome não pode ser branco!");
nome = value;
}
}
public double Preco {
get {
return preco;
}
set {
if (value < 0) throw new ArgumentException("O preço não pode ser negativo!");
preco = value;
}
}
}
Agora podemos simplesmente usar a classe assim:
Fruta fruta = new Fruta();
fruta.Nome = "Maçã"; //Chama o set da propriedade Nome
fruta.Preco = -5.0f; //Chame o set da propriedade preço, que lança argument exception.
Sobrecarga de operadores
No C#, você pode fazer com que uma classe funcione com operadores como +, -, * e /. Isso permite, por exemplo, que você use um List assim:
//Inicialização, similar ao java
IList<int> lista = new List<int>();
lista.add(10);
//Uso com operador de []
int x = lista[0]; //x agora vale 10
lista[0] = 5; //Atribui o valor 5 a posição 0 da lista.
O mesmo pode ser feito para classes matemáticas, e classes representando tipos numéricos (como BigInteger e BigDecimal). Compare o código da classe Vector2D feito em Java e em C#:
//Inicialização: Java e C#
Vector2D v1 = new Vector2D(10,20);
Vector2D v2 = new Vector2D(20,50);
Vector2D v3 = new Vector2D(20,50);
//Conta em C#
Vector2D v = 5 * (v1 - v2/2) + v3;
//Conta em java
Vector2D v = v1.subtract(v2.divide(2)).multiply(5).add(v3);
Note que no Java a multiplicação por 5 teve obrigatoriamente de ser invertida, pois o número 5 não teria o método multiply. Sorte que a operação é comutativa.
Extension methods
Permite que você associe a uma classe um método, mesmo que você não possua seu fonte. Isso só é possível se o método só faz uso da parte pública da classe.
Por exemplo, digamos que vc queira fazer um método chamado toCsv(), para qualquer List. No java, você seria obrigado a fazer um método estático:
public class ListUtil {
public static <T> String toCsv(List<T> lista) {
StringBuilder sb = new StringBuilder();
for (T obj : lista) {
sb.append(obj.toString()).append(",");
}
sb.delete(sb.lastIndexOf(","));
}
}
String csv = ListUtil.toCsv(lista);
No C#, você pode criar um extension method:
public static class ListUtil {
public static <T> string toCsv(this List<T> lista) {
StringBuilder sb = new StringBuilder();
foreach (T obj in lista) {
sb.Append(obj.ToString()).Append(",");
}
sb.Delete(sb.LastIndexOf(","));
}
}
//E agora chamamos como se toCsv() fosse um método!
String csv = lista.toCsv();
LINQ
Vamos dizer que em Java vc tenha um List, contendo a classe Fruta, que tem no seu atributo nome: "Abóbora", "Limão", "Abóbora", "Maçã", "Pêra", "Caqui", "Limão", "Melância", "Amora".
E para cada um o preço.
E que você queira gerar um outro List, com o nome de todas as frutas que custam menos de R$5,00, sem repetição de nomes, em ordem reversa. Como você faria?
Em java, isso seria a seguinte tarefa tediosa:
1. Criar um TreeSet, usando o String.ReverseComparator como entrada
2. Percorrer a lista de frutas, fazendo um if para localizar todas que custam menos de 10 e copia-las no TreeSet
3. Copiar o TreeSet para uma lista.
No C#, você faz assim:
List<string> frutasBaratas =
(from fruta in frutas
where fruta.Preco < 10
select distinct fruta.Nome).ToList();
O LINQ também funciona para tabelas de banco de dados e XML.
Partial classes
Não vou entrar em detalhes da sintaxe, mas permite que a mesma classe seja implementado em dois arquivos. Se o Java tivesse isso, o Netbeans poderia pegar todo trecho que ele deixa em azul nas classes do Swing e colocar em um lugar, enquanto você edita um arquivo limpo com o resto da classe em outro.
Cálculo Lambda
Quanto ao lambda. É um recurso que será adicionado ao Java 8, e que já foi adicionado ao C++11, e está há um bom tempo no C#. Trata-se da implementação de closures na linguagem, o que a aproxima do paradigma de programação funcional. Trata-se de outro paradigma e explica-lo levaria um bocado de tempo, mas surgiro que procure sobre o assunto quanto tiver tempo.
Compilação condicional
Já teve algum código que você gostaria que fosse executado apenas se você estivesse em modo debug? Ou que tal algum trecho que não fosse? No C# é possível:
void apagarBaseDeDados() {
#if TESTE_UNITARIO
executarSql("ExcluirBaseInteira.sql");
#else
throw new ArgumentException("A base de dados só pode ser apagada na compilação de testes unitários!");
#endif
}
Isso garante que nenhum programador irá acidentalmente apagar a base de dados de produção, nem que um código com esse método poderosíssimo será enviado para o servidor.
Aquele "TESTE_UNITARIO" você configura no seu ambiente de compilação. Se ele não estiver presente, o método apagarBaseDeDados() será compilado apenas com a mensagem de erro.
Se ele estiver presente, aí sim, ele fará a exclusão da base. Note que no assembly final não existe o if. A compilação terá uma coisa ou outra.
Essa diretiva é bem útil quando você quer gerar multiplataforma que interaja com código nativo.