¿Viola algún principio de OOP si una función miembro no utiliza ninguna de las propiedades de clase / variables miembro?
No.
OOP no le importa si su función miembro usa, o no usa, propiedades de clase o variables miembro. OOP se preocupa por el polimorfismo y no por la implementación de codificación dura. Las funciones estáticas tienen sus usos, pero una función no debería ser estática simplemente porque no depende del estado del objeto. Si eso es lo que piensas bien, pero no culpes a OOP porque esa idea no vino de OOP.
¿Es [es] un mal diseño [para no] hacer uso de las variables miembro?
Si no necesita recordar el estado de una llamada a otra, no hay una buena razón para usar el estado.
¿Qué principio del diseño orientado a objetos viola?
Ninguna.
Si una función miembro no usa la variable miembro, ¿esa función miembro siempre debe hacerse estática?
No. Este pensamiento tiene la flecha de implicación que va en la dirección equivocada.
Una función estática no puede acceder al estado de la instancia
Si la función no tiene necesidad de acceder al estado de instancia, entonces la función puede ser estática o no estática
Hacer que la función sea estática aquí depende completamente de usted. Pero lo hará más como un global si lo hace. Antes de volverse estático, considere alojar la función en una clase sin estado. Es mas flexible.
Tengo aquí un ejemplo de OOP de una función miembro que no usa propiedades de clase o variables miembro.
La función miembro (y su clase sin estado) :
#include <iostream>
class Strategy
{
public:
virtual int execute (int a, int b) = 0; // execute() is a so-called pure virtual
// function. As a consequence, Strategy
// is a so-called abstract class.
};
Tres implementaciones diferentes:
class ConcreteStrategyAdd:public Strategy
{
public:
int execute(int a, int b)
{
std::cout << "Called ConcreteStrategyAdd's execute()\n";
return a + b;
}
};
class ConcreteStrategySubstract:public Strategy
{
public:
int execute(int a, int b)
{
std::cout << "Called ConcreteStrategySubstract's execute()\n";
return a - b;
}
};
class ConcreteStrategyMultiply:public Strategy
{
public:
int execute(int a, int b)
{
std::cout << "Called ConcreteStrategyMultiply's execute()\n";
return a * b;
}
};
Un lugar para almacenar la elección de implementación:
class Context
{
private:
Strategy* pStrategy;
public:
Context (Strategy& strategy)
: pStrategy(&strategy)
{
}
void SetStrategy(Strategy& strategy)
{
pStrategy = &strategy;
}
int executeStrategy(int a, int b)
{
return pStrategy->execute(a,b);
}
};
Un ejemplo de uso
int main()
{
ConcreteStrategyAdd concreteStrategyAdd;
ConcreteStrategySubstract concreteStrategySubstract;
ConcreteStrategyMultiply concreteStrategyMultiply;
Context context(concreteStrategyAdd);
int resultA = context.executeStrategy(3,4);
context.SetStrategy(concreteStrategySubstract);
int resultB = context.executeStrategy(3,4);
context.SetStrategy(concreteStrategyMultiply);
int resultC = context.executeStrategy(3,4);
std::cout << "\nresultA: " << resultA
<< "\nresultB: " << resultB
<< "\nresultC: " << resultC
<< "\n";
}
Salidas:
Called ConcreteStrategyAdd's execute()
Called ConcreteStrategySubstract's execute()
Called ConcreteStrategyMultiply's execute()
resultA: 7
resultB: -1
resultC: 12
Y todo sin execute()
preocuparse por el estado de ningún objeto. La Strategy
clase en realidad no tiene estado. Solo el estado está adentro Context
. Los objetos sin estado están perfectamente bien en OOP.
Encontré este código aquí .