Si tengo un constructor con 2 parámetros obligatorios y 4 parámetros opcionales, cómo puedo evitar escribir 16 constructores o incluso los 10 o más constructores que tendría que escribir si utilizaba parámetros predeterminados (que no me gusta porque es una auto documentación pobre) ¿Hay algún modismo o método utilizando plantillas que pueda usar para que sea menos tedioso? (¿Y más fácil de mantener?)evitando el tedio de los parámetros opcionales
Respuesta
Puede que le interese el Named Parameter Idiom.
Para resumir, cree una clase que contenga los valores que desea pasar a su constructor (es). Agregue un método para establecer cada uno de esos valores, y haga que cada método haga un return *this;
al final. Tener un constructor en tu clase que tome una referencia directa a esta nueva clase. Esto se puede usar de la siguiente manera:
class Person;
class PersonOptions
{
friend class Person;
string name_;
int age_;
char gender_;
public:
PersonOptions() :
age_(0),
gender_('U')
{}
PersonOptions& name(const string& n) { name_ = n; return *this; }
PersonOptions& age(int a) { age_ = a; return *this; }
PersonOptions& gender(char g) { gender_ = g; return *this; }
};
class Person
{
string name_;
int age_;
char gender_;
public:
Person(const PersonOptions& opts) :
name_(opts.name_),
age_(opts.age_),
gender_(opts.gender_)
{}
};
Person p = PersonOptions().name("George").age(57).gender('M');
¿Cómo harías ese trabajo en un constructor? ¿Usando 'return this' en el método constructor? –
Obviamente, no puede devolver nada de un constructor. Pero puede usar una copia, como 'Foo f = Foo(). Option1(). Option2();' por ejemplo. El ejemplo en el enlace usa una clase separada para hacer la creación real. –
@Robert es importante notar que el lado derecho comienza con 'PersonOptions', no' Person'. Esto crea un objeto supuestamente liviano y luego tiene varias llamadas a métodos para establecer propiedades a valores no predeterminados. Luego hay un ctor llamado 'Persona (const PersonOptions &)' y ta da. La instanciación de un objeto (por ejemplo, 'PersonOptions()') deja "* this" en el contexto actual para que puedas .method() de inmediato. Sin embargo, cada método todavía necesita 'devolver * esto' para poder encadenarlo. –
¿Qué pasa si hace un objeto de parámetro que contenga todos los campos? Entonces podrías pasar eso y simplemente establecer los campos que necesites. Probablemente hay un nombre para ese patrón, no está seguro de lo que es aunque ...
ACTUALIZACIÓN:
Código podría parecer un poco esto:
paramObj.x=1;
paramObj.y=2;
paramObj.z=3;
paramObj.magic=true;
... //set many other "parameters here"
someObject myObject = new someObject(paramObj);
y dentro del constructor Puede someObject
establecer valores predeterminados para las cosas que no estaban ya establecidas (o generar un error si era obligatorio).
Honestamente, no soy un gran admirador de esta solución, pero la he usado una o dos veces cuando paramObj
tiene sentido al contener un conjunto de datos que generalmente van juntos (para que podamos usarlo durante más de solo constructores), y era mejor que múltiples constructores. Descubrí que era feo pero funcionó, YMMV.
... y este objeto de parámetro establecería valores predeterminados en su constructor predeterminado. – Danvil
¿Por qué es mejor que construir el objeto original y las propiedades de configuración? –
@Johannes: ¿No es solo la parábola de parámetros nombrados que Fred Larson menciona en su respuesta? –
Y ahora para el "Boost tiene algo para que" la respuesta:
El Boost Parameter Library parece ser un buen ajuste a su caso de uso.
Todo nuevo para C++ 17
#include <optional>
using optional_int = std::optional<int>;
class foo {
int arg0, arg1; // required
int arg2, arg3; // optional
const int default_2 = -2;
const int default_3 = -3;
public:
foo(int arg0, int arg1, optional_int opt0 = {}, optional_int opt1 = {})
: arg0(arg0), arg1(arg1)
, arg2(opt0.value_or(default_2))
, arg3(opt1.value_or(default_3))
{ }
};
int main() {
foo bar(42, 43, {}, 45); // Take default for opt0 (arg2)
return 0;
}
I tienen una implementación spline cúbica que permite al usuario opcionalmente para especificar la primera derivada, ya sea en el extremo izquierdo, el extremo derecho, o ambos. Si no se especifica una derivada, entonces el código en efecto calcula una, al asumir que la segunda derivada es cero (la llamada "spline natural"). Aquí hay un fragmento para el extremo izquierdo.
// Calculate the second derivative at the left end point
if (!left_deriv.has_value()) {
ddy[0]=u[0]=0.0; // "Natural spline"
} else {
const real yP0 = left_deriv.value();
ddy[0] = -0.5;
u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yP0);
}
- 1. Parámetros opcionales de Linq
- 2. ¿Cómo manejo los parámetros opcionales en Moose?
- 3. Parámetros de salida opcionales
- 4. Rubí parámetros opcionales
- 5. Python parámetros opcionales
- 6. parámetros opcionales en CodeIgniter
- 7. Parámetros opcionales con Specflow
- 8. Router_Route con parámetros opcionales
- 9. Cómo obtener el constructor predeterminado cuando los parámetros son opcionales
- 10. \ newcommand/\ newenvironment - parámetros opcionales
- 11. Activator.CreateInstance con parámetros opcionales
- 12. Parámetros opcionales en el servicio web ASP.NET
- 13. Parámetros opcionales para las interfaces
- 14. Enterprise Architect: C# ¿Parámetros opcionales?
- 15. Ruby Métodos y parámetros opcionales
- 16. Parámetros nombrados/opcionales en Delphi?
- 17. Omisión de los parámetros de funciones opcionales en JavaScript
- 18. Menos css con parámetros opcionales
- 19. spring-data-mongo - parámetros de consulta opcionales?
- 20. enrutamientos de asp.net webforms: parámetros opcionales
- 21. getopt no analiza argumentos opcionales para los parámetros
- 22. Python constructor hace cosas raras con los parámetros opcionales
- 23. Métodos en conflicto sobrecargados con los parámetros opcionales
- 24. Parámetros de obtención opcionales en django?
- 25. ¿Cómo funcionan los parámetros opcionales en Let/Get Properties?
- 26. ¿Cómo manejar los parámetros opcionales en la consulta SQL?
- 27. ambigüedad en la interpretación de parámetros opcionales
- 28. rieles url_for el nombre de ruta con parámetros opcionales
- 29. constructor/método de Java con parámetros opcionales?
- 30. Especificación facultativa de algunos parámetros opcionales C#
¿Estás seguro de que tu clase no está tratando de hacer demasiado? –
@Johannes: Quiere la posibilidad de omitir say d sin forzar a la persona que llama a conocer su valor predeterminado. – Danvil
@John: puedo ver a qué te refieres, pero los parámetros pueden ser propiedades. Por ejemplo, tengo una clase de botón GUI que tiene muchas propiedades, como imagen, texto, tamaño, color, etc., pero no creo que sea "demasiado". En mi humilde opinión, los botones tienen un propósito muy específico y son fáciles de encajar en una sola clase en la que el usuario sabrá de inmediato qué hace la clase. – Kyle