Properties
Em linguagens OO, costumam ser padrões as seguintes regras:
- Todo atributo deve ser inacessível às outras classes;
- Se um atributo pode ser lido externamente, essa leitura deve se dar a partir de um getter;
- Se um atributo pode ser escrito por elementos externos, essa escrita deve se dar a partir de um setter.
Em algumas delas, a forma como isso é feito é extremamente manual, como Java por exemplo:
public class A {
private int something;
private SomeType another;
public int getSomething() {
return something;
}
public void setSomething(int value) {
something = value;
}
public SomeType getAnother() {
return another;
}
public void setAnother(SomeType value) {
another = value;
}
}
Em C#, felizmente há uma maneira simples de lidar com getters e setters,
que é através de Properties. Para quem conhece Ruby, é semelhante a
attr_accessor
, attr_reader
e attr_writer
: eles geram métodos que fazem a
devida função de getter e setter para você. Para quem conhece Python, é
como utilizar @property
:
public class A {
public int Something {
get; set;
}
public SomeType Another {
get; set;
}
}
Em alguns casos, é necessário definir como esses métodos são implementados. Por exemplo, há momentos em que não é possível expor algum atributo como Property diretamente, então é necessário separá-lo como um atributo e utilizar a Property para o expor:
public class A {
private Type _somethingThatCantBeAProperty;
public Type SomethingThatCantBeAProperty {
// get e set são efetivamente métodos, então...podemos simplesmente
// utilizar os métodos para retornar os valores que queremos.
get
{
return _somethingThatCantBeAProperty;
}
set
{
// Em um setter, o valor passado após o "=" é dado como `value`.
_somethingThatCantBeAProperty = value;
}
}
}
public class Application {
public static void Main(string[] args) {
var a = new A();
// chama o set
a.SomethingThatCantBeAProperty = new Type();
// chama o get
Console.WriteLine(a.SomethingThatCantBeAProperty);
}
}
Quando utilizar properties: sempre que você tiver um atributo público (com getter e setter), faça-o como uma property (ou encapsule-o com, caso não seja possível ele em si ser uma property). Não utilize properties caso o setter ou o getter envolva algum cálculo! Nesse caso, use um método explícito, a fim de manter a intuitividade de que o acesso aquele valor não é necessariamente trivial/barato.