¿Es bueno que todas las funciones del setter devuelvan una referencia al objeto en C++?¿Es bueno tener todas las funciones del setter para devolver una referencia al objeto en C++?
Respuesta
Es un patrón lo suficientemente útil si hay muchas cosas que se deben establecer en un objeto.
class Foo
{
int x, y, z;
public:
Foo &SetX(int x_) { x = x_; return *this; }
Foo &SetY(int y_) { y = y_; return *this; }
Foo &SetZ(int z_) { z = z_; return *this; }
};
int main()
{
Foo foo;
foo.SetX(1).SetY(2).SetZ(3);
}
Este modelo sustituye a un constructor que toma tres enteros:
int main()
{
Foo foo(1, 2, 3); // Less self-explanatory than the above version.
}
Es útil si tiene un número de valores que no siempre necesitan ser ajustados.
Como referencia, un ejemplo más completo de este tipo de técnica se denomina "Named Parameter Idiom" en C++ FAQ Lite.
Por supuesto, si está utilizando esto para los parámetros con nombre, es posible que desee echar un vistazo a boost::parameter. O puede que no ...
No lo creo. Por lo general, piensas en el objeto 'setter' como haciendo exactamente eso.
Además, si acaba de configurar el objeto, ¿no tiene un puntero de todos modos?
No todos los ajustadores, pero algunos de ellos podrían devolver la referencia al objeto para ser útiles.
tipo de
a.SetValues(object)(2)(3)(5)("Hello")(1.4);
utilicé hace esta vez mucho tiempo para construir generador de expresiones SQL que maneja todos los problemas de fugas y otras cosas.
SqlBuilder builder;
builder.select(column1)(column2)(column3).
where("=")(column1, value1)
(column2, value2).
where(">")(column3, 100).
from(table1)("table2")("table3");
No pude reproducir las fuentes en 10 minutos. Entonces la implementación está detrás de las cortinas.
He hecho cosas similares para construir documentos XML en C++. La pregunta aquí parece ser acerca de los generadores de propiedades generales. –
Puede devolver una referencia a this
si quieres función setter cadena de llamadas entre sí de esta manera:
obj.SetCount(10).SetName("Bob").SetColor(0x223344).SetWidth(35);
personalmente creo que el código es difícil de leer que la alternativa:
obj.SetCount(10);
obj.SetName("Bob");
obj.SetColor(0x223344);
obj.SetWidth(35);
Es una cuestión de diseño. Puedes simplemente escribir la primera parte como la segunda, simplemente omitiendo obj. en todo menos en el primero y; en todo menos en el último. En mi humilde opinión, es tan fácil de leer. –
Si su motivación está relacionada con el encadenamiento (por ejemplo, la sugerencia de Brian Ensink), ofrecería dos comentarios:
1. If yo Usted se encuentra frecuentemente configurando muchas cosas a la vez, lo que puede significar que debe producir un struct
o class
que contenga todas estas configuraciones para que puedan pasar todas a la vez. El siguiente paso podría ser usar struct
o class
en el objeto en sí ... pero como está utilizando getters y setters, la decisión de cómo representarlo internamente será transparente para los usuarios de la clase de todos modos, por lo que esta decisión se relacionan más con cuán compleja es la clase que cualquier otra cosa.
2. Una alternativa a un colocador es crear un objeto nuevo, cambiarlo y devolverlo. Esto es a la vez ineficiente e inapropiado en la mayoría de los tipos, especialmente los tipos mutables. Sin embargo, es una opción que la gente a veces olvida, a pesar de su uso en la clase de cadena de muchos idiomas.
Esta técnica se utiliza en el Named parameter Idiom.
El propósito típico para este estilo está en uso para la construcción de objetos.
Person* pPerson = &(new Person())->setAge(34).setId(55).setName("Jack");
en lugar de
Person* pPerson = new Person(34, 55, "Jack");
Usando el segundo más estilo tradicional se podría olvidar si el primer valor que se pasa al constructor fue la edad o la identificación? Esto también puede conducir a múltiples constructores basados en la validez de algunas propiedades.
Utilizando el primero de estilo podría olvide de establecer algunas de las propiedades de los objetos y los insectos y puede dar lugar donde los objetos no son 'totalmente' construidos. (Se agrega una propiedad de clase en un punto posterior pero no todas las ubicaciones de construcción se actualizaron para llamar al instalador requerido).
A medida que el código evoluciona me gusta mucho el hecho de que puedo usar el compilador para ayudarme a encontrar todos los lugares donde se crea un objeto al cambiar la firma de un constructor. Por eso, prefiero usar constructores comunes de C++ sobre este estilo.
Este patrón podría funcionar bien en aplicaciones que mantienen su modelo de datos a través del tiempo de acuerdo con reglas similares a los utilizados en muchas aplicaciones de bases de datos:
- Puede agregar un campo/atributo a una tabla/clase que es NULL por defecto. (Por lo tanto la actualización de los datos existentes requiere sólo una nueva columna NULL en la base de datos.)
- código que es no cambios debería funcionar lo mismo con este campo NULL añadió.
+1 para seguridad en tiempo de compilación. – Eclipse
Wow. Es una adaptación increíble a la falta de parámetros nombrados de C++ (como Ada lo ha tenido durante 20 años). –
-> no. para los indicadores sin embargo :) –
OMI emisores son un olor código que generalmente indica una de dos cosas:
de tomar una Mountian fuera de un grano de arena
Si usted tiene una clase como esta:
class Gizmo
{
public:
void setA(int a) { a_ = a; }
int getA() const { return a_; }
void setB(const std::string & b) { v_ = b; }
std::string getB() const { return b_; }
private:
std::string b_;
int a_;
};
... y los valores realmente son así de simple, entonces ¿por qué no hacer que los miembros de datos público ?:
class Gizmo
{
public:
std::string b_;
int a_;
};
... mucho más simple y, si los datos son de simple usted no pierde nada.
Otra posibilidad es que usted podría ser
Hacer un grano de arena fuera de un Mountian
Muchas veces los datos no es así de simple: tal vez usted tiene que cambiar varios valores, hacer algo de computación, notificar algún otro objeto; quién sabe qué. Pero si los datos no son lo suficientemente triviales como para necesitar realmente setters & getters, entonces no es tan trivial como para necesitar el manejo de errores también. Entonces, en esos casos, los usuarios getters & deberían devolver algún tipo de código de error o hacer algo diferente para indicar que algo malo sucedió.
Si está encadenando llamadas entre sí de esta manera:
A.doA().doB().doC();
... y DOA() falla, lo que realmente quieres a estar llamando DOB () y Doc() de todos modos? Lo dudo.
RE: "A.doA(). DoB(). DoC();" si doA falla, para eso están las excepciones. – Eclipse
+1, buen punto John. También es bueno señalar a Josh. –
- 1. ¿Es bueno tener un DatabaseManager con todas las funciones de todos los objetos del modelo?
- 2. ¿Es posible devolver una referencia a una variable en C#?
- 3. Buscar todas las funciones existentes para las dependencias del paquete?
- 4. ¿es una mejor práctica devolver un objeto complejo o utilizar parámetros de referencia/salida?
- 5. Funciones de referencia en C++
- 6. Obtenga todas las funciones definidas para un objeto
- 7. Documentando funciones del setter con roxygen
- 8. ¿Sería bueno un operador de referencia condicional en C#?
- 9. devolver todas las filas duplicadas
- 10. Retorno todas las propiedades de un objeto en Objective-C
- 11. ¿Cómo devolver un objeto de clase por referencia en C++?
- 12. C++: devolver por referencia y copiar constructores
- 13. ¿Por qué debería el operador de asignación devolver una referencia al objeto?
- 14. Obtener todas las funciones de un objeto en JavaScript
- 15. C# - ¿Aplicación para mostrar todas las dependencias entre funciones?
- 16. ¿El lanzamiento de un objeto en C# siempre devuelve una referencia al objeto inicial?
- 17. ¿Listar todas las propiedades del objeto ventana?
- 18. Utilizando C# MethodInvoker.Invoke() para una aplicación GUI ... es tan bueno?
- 19. ¿Cómo "devolver un objeto" en C++?
- 20. ¿Bajo qué condiciones es bueno tener una "clase parcial"?
- 21. ¿Hay una forma correcta de devolver una nueva instancia de objeto por referencia en C++?
- 22. ¿Es bueno learncpp.com para principiantes?
- 23. ¿Cuándo es bueno usar pasar por referencia en PHP?
- 24. funciones dentro de las funciones en C
- 25. ¿Es bueno tener la clase "Utils" en su proyecto de software?
- 26. Devolver el objeto C++ a Java
- 27. Devolver un objeto vs devolver una tupla
- 28. ¿Debo declarar todas las funciones virtuales en una clase base?
- 29. ¿Cómo acceder al objeto primario desde las funciones lambda?
- 30. ¿Es bueno tener un constructor en clase abstracta?
Últimamente me he sentido intrigado por esta técnica. Será interesante ver si alguien presenta algún inconveniente. –
Interesante. No lo había considerado una alternativa a los constructores complejos. Esta técnica podría reducir un gran número de sobrecargas de constructor. –
Hay algunas cosas que no puede hacer con esto que puede hacer con los constructores (por ejemplo, inicializaciones y referencias) – Eclipse