Los accesorios son más que campos. Otros ya han señalado varias diferencias importantes, y voy a agregar una más.
Las propiedades participan en las clases de interfaz. Por ejemplo:
interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
Esta interfaz se puede satisfacer de varias maneras. Por ejemplo:
class Person: IPerson
{
private string _name;
public string FirstName
{
get
{
return _name ?? string.Empty;
}
set
{
if (value == null)
throw new System.ArgumentNullException("value");
_name = value;
}
}
...
}
En esta implementación estamos protegiendo tanto a la clase Person
de entrar en un estado no válido, así como la persona que llama de conseguir nula hacia fuera de la propiedad sin asignar.
Pero podríamos impulsar el diseño aún más. Por ejemplo, la interfaz puede no tratar con el colocador.Es muy legítimo decir que los consumidores de IPerson
interfaz sólo están interesados en conseguir la propiedad, no en su creación:
interface IPerson
{
string FirstName { get; }
string LastName { get; }
}
aplicación anterior de las satisface clase Person
esta interfaz. El hecho de que le permite al llamador también establecer las propiedades no tiene sentido desde el punto de vista de los consumidores (que consumen IPerson
). La funcionalidad adicional de la aplicación concreta se toma en consideración, por ejemplo, el constructor:
class PersonBuilder: IPersonBuilder
{
IPerson BuildPerson(IContext context)
{
Person person = new Person();
person.FirstName = context.GetFirstName();
person.LastName = context.GetLastName();
return person;
}
}
...
void Consumer(IPersonBuilder builder, IContext context)
{
IPerson person = builder.BuildPerson(context);
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
En este código, el consumidor no sabe nada de los emisores de propiedad - no es su negocio saber acerca de ella. El consumidor solo necesita getters, y obtiene getters de la interfaz, es decir, del contrato.
Otra aplicación completamente válida de IPerson
sería una clase de persona inmutable y una fábrica de quien corresponda:
class Person: IPerson
{
public Person(string firstName, string lastName)
{
if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName))
throw new System.ArgumentException();
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; private set; }
public string LastName { get; private set; }
}
...
class PersonFactory: IPersonFactory
{
public IPerson CreatePerson(string firstName, string lastName)
{
return new Person(firstName, lastName);
}
}
...
void Consumer(IPersonFactory factory)
{
IPerson person = factory.CreatePerson("John", "Doe");
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
En este ejemplo de código de consumo, una vez más no tiene conocimiento de las propiedades de relleno. El consumidor solo se ocupa de los getters y la implementación concreta (y la lógica de negocios subyacente, como probar si el nombre está vacío) se deja en manos de las clases especializadas: constructores y fábricas. Todas estas operaciones son completamente imposibles con los campos.
posible duplicado de [getters y setters implementados automáticamente frente a campos públicos] (http://stackoverflow.com/questions/111461/auto-implemented-getters-and-setters-vs-public-fields) – nawfal